瀏覽代碼

Merge branch '5.8.x' into 6.2.x

Josh Cummings 8 月之前
父節點
當前提交
348f064df1
共有 1 個文件被更改,包括 72 次插入0 次删除
  1. 72 0
      docs/modules/ROOT/pages/servlet/integrations/websocket.adoc

+ 72 - 0
docs/modules/ROOT/pages/servlet/integrations/websocket.adoc

@@ -205,6 +205,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<MessageAuthorizationContext<?>> {
+
+	private SecurityExpressionHandler<Message<?>> 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> 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<Message<?>> 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<Message<?> {
+        messages
+            // ..
+            .simpSubscribeDestMatchers("/topic/friends/{friends}").access(MessageExpressionAuthorizationManager("#friends == 'john"))
+            // ...
+
+        return messages.build()
+    }
+}
+----
+======
+
 [[websocket-authorization-notes]]
 === WebSocket Authorization Notes