From 6ea7da51780247b1537d084a330d39a6ecbec00c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 01:04:48 +0000 Subject: [PATCH 1/3] Bump antora from 3.2.0-alpha.6 to 3.2.0-alpha.8 in /docs Bumps [antora](https://gitlab.com/antora/antora) from 3.2.0-alpha.6 to 3.2.0-alpha.8. - [Changelog](https://gitlab.com/antora/antora/blob/main/CHANGELOG.adoc) - [Commits](https://gitlab.com/antora/antora/compare/v3.2.0-alpha.6...v3.2.0-alpha.8) --- updated-dependencies: - dependency-name: antora dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index a41cc3cb8c..32d13e1e59 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "antora": "3.2.0-alpha.6", + "antora": "3.2.0-alpha.8", "@antora/atlas-extension": "1.0.0-alpha.2", "@antora/collector-extension": "1.0.0", "@asciidoctor/tabs": "1.0.0-beta.6", From cac03995a318f3e605a9be69a7b270255fdf808a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 01:04:51 +0000 Subject: [PATCH 2/3] Bump @antora/collector-extension from 1.0.0 to 1.0.1 in /docs --- updated-dependencies: - dependency-name: "@antora/collector-extension" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index 32d13e1e59..567c1f3a68 100644 --- a/docs/package.json +++ b/docs/package.json @@ -2,7 +2,7 @@ "dependencies": { "antora": "3.2.0-alpha.8", "@antora/atlas-extension": "1.0.0-alpha.2", - "@antora/collector-extension": "1.0.0", + "@antora/collector-extension": "1.0.1", "@asciidoctor/tabs": "1.0.0-beta.6", "@springio/antora-extensions": "1.14.2", "@springio/asciidoctor-extensions": "1.0.0-alpha.14" From 8b9fe13c884a35ff87af409fe2546a5042a38bc7 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:25:33 -0700 Subject: [PATCH 3/3] Document Messaging SpEL Migration Issue gh-12650 --- .../pages/servlet/integrations/websocket.adoc | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc b/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc index 635ea29def..06cf3aa3a9 100644 --- a/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc +++ b/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc @@ -208,6 +208,78 @@ This will ensure that: <5> Any other message of type MESSAGE or SUBSCRIBE is rejected. Due to 6 we do not need this step, but it illustrates how one can match on specific message types. <6> Any other Message is rejected. This is a good idea to ensure that you do not miss any messages. +[[migrating-spel-expressions]] +=== Migrating SpEL Expressions + +If you are migrating from an older version of Spring Security, your destination matchers may include SpEL expressions. +It's recommended that these be changed to using concrete implementations of `AuthorizationManager` since this is independently testable. + +However, to ease migration, you can also use a class like the following: + +[source,java] +---- +public final class MessageExpressionAuthorizationManager implements AuthorizationManager> { + + private SecurityExpressionHandler> expressionHandler = new DefaultMessageSecurityExpressionHandler(); + + private Expression expression; + + public MessageExpressionAuthorizationManager(String expressionString) { + Assert.hasText(expressionString, "expressionString cannot be empty"); + this.expression = this.expressionHandler.getExpressionParser().parseExpression(expressionString); + } + + @Override + public AuthorizationDecision check(Supplier authentication, MessageAuthorizationContext context) { + EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context.getMessage()); + boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, ctx); + return new ExpressionAuthorizationDecision(granted, this.expression); + } + +} +---- + +And specify an instance for each matcher that you cannot get migrate: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Configuration +public class WebSocketSecurityConfig { + + @Bean + public AuthorizationManager> messageAuthorizationManager(MessageMatcherDelegatingAuthorizationManager.Builder messages) { + messages + // ... + .simpSubscribeDestMatchers("/topic/friends/{friend}").access(new MessageExpressionAuthorizationManager("#friends == 'john")); + // ... + + return messages.build(); + } +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Configuration +open class WebSocketSecurityConfig { + fun messageAuthorizationManager(messages: MessageMatcherDelegatingAuthorizationManager.Builder): AuthorizationManager { + messages + // .. + .simpSubscribeDestMatchers("/topic/friends/{friends}").access(MessageExpressionAuthorizationManager("#friends == 'john")) + // ... + + return messages.build() + } +} +---- +====== + [[websocket-authorization-notes]] === WebSocket Authorization Notes