2626import org .apache .commons .logging .LogFactory ;
2727
2828import org .springframework .core .log .LogMessage ;
29- import org .springframework .http .server .PathContainer ;
3029import org .springframework .messaging .Message ;
3130import org .springframework .messaging .simp .SimpMessageType ;
3231import org .springframework .security .authorization .AuthenticatedAuthorizationManager ;
3635import org .springframework .security .authorization .SingleResultAuthorizationManager ;
3736import org .springframework .security .core .Authentication ;
3837import org .springframework .security .messaging .util .matcher .MessageMatcher ;
38+ import org .springframework .security .messaging .util .matcher .MessageMatcherFactory ;
3939import org .springframework .security .messaging .util .matcher .PathPatternMessageMatcher ;
4040import org .springframework .security .messaging .util .matcher .SimpDestinationMessageMatcher ;
4141import org .springframework .security .messaging .util .matcher .SimpMessageTypeMatcher ;
4242import org .springframework .util .AntPathMatcher ;
4343import org .springframework .util .Assert ;
44+ import org .springframework .util .CollectionUtils ;
4445import org .springframework .util .PathMatcher ;
4546import org .springframework .util .function .SingletonSupplier ;
46- import org .springframework .web .util .pattern .PathPatternParser ;
4747
4848public final class MessageMatcherDelegatingAuthorizationManager implements AuthorizationManager <Message <?>> {
4949
@@ -89,13 +89,16 @@ public AuthorizationDecision check(Supplier<Authentication> authentication, Mess
8989 }
9090
9191 private MessageAuthorizationContext <?> authorizationContext (MessageMatcher <?> matcher , Message <?> message ) {
92- if (!matcher .matches ((Message ) message )) {
92+ MessageMatcher .MatchResult matchResult = matcher .matcher ((Message ) message );
93+ if (!matchResult .isMatch ()) {
9394 return null ;
9495 }
95- if (matcher instanceof Builder .LazySimpDestinationMessageMatcher pathMatcher ) {
96- return new MessageAuthorizationContext <>(message , pathMatcher .extractPathVariables (message ));
96+
97+ if (!CollectionUtils .isEmpty (matchResult .getVariables ())) {
98+ return new MessageAuthorizationContext <>(message , matchResult .getVariables ());
9799 }
98- if (matcher instanceof Builder .LazySimpDestinationPatternMessageMatcher pathMatcher ) {
100+
101+ if (matcher instanceof Builder .LazySimpDestinationMessageMatcher pathMatcher ) {
99102 return new MessageAuthorizationContext <>(message , pathMatcher .extractPathVariables (message ));
100103 }
101104 return new MessageAuthorizationContext <>(message );
@@ -119,8 +122,6 @@ public static final class Builder {
119122 @ Deprecated
120123 private Supplier <PathMatcher > pathMatcher = AntPathMatcher ::new ;
121124
122- private boolean useHttpPathSeparator = true ;
123-
124125 public Builder () {
125126 }
126127
@@ -157,159 +158,70 @@ public Builder.Constraint simpTypeMatchers(SimpMessageType... typesToMatch) {
157158 }
158159
159160 /**
160- * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances without
161- * regard to the {@link SimpMessageType}. If no destination is found on the
162- * Message, then the Matcher returns false.
163- * @param patterns the patterns to create
164- * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher}
165- * from.
166- * @deprecated use {@link #destinationPathPatterns(String...)}
161+ * Maps a {@link List} of {@link SimpDestinationMessageMatcher} (or
162+ * {@link PathPatternMessageMatcher} if the application has configured a
163+ * {@link org.springframework.security.messaging.util.matcher.PathPatternMessageMatcherBuilderFactoryBean})
164+ * instances without regard to the {@link SimpMessageType}. If no destination is
165+ * found on the Message, then the Matcher returns false.
166+ * @param patterns the patterns to create {@code MessageMatcher}s from.
167167 */
168- @ Deprecated
169168 public Builder .Constraint simpDestMatchers (String ... patterns ) {
170169 return simpDestMatchers (null , patterns );
171170 }
172171
173172 /**
174- * Allows the creation of a security {@link Constraint} applying to messages whose
175- * destinations match the provided {@code patterns}.
176- * <p>
177- * The matching of each pattern is performed by a
178- * {@link PathPatternMessageMatcher} instance that matches irrespectively of
179- * {@link SimpMessageType}. If no destination is found on the {@code Message},
180- * then each {@code Matcher} returns false.
181- * </p>
182- * @param patterns the destination path patterns to which the security
183- * {@code Constraint} will be applicable
184- * @since 6.5
173+ * Maps a {@link List} of {@link SimpDestinationMessageMatcher} (or
174+ * {@link PathPatternMessageMatcher} if the application has configured a
175+ * {@link org.springframework.security.messaging.util.matcher.PathPatternMessageMatcherBuilderFactoryBean})
176+ * instances that match on {@code SimpMessageType.MESSAGE}. If no destination is
177+ * found on the Message, then the Matcher returns false.
178+ * @param patterns the patterns to create {@code MessageMatcher}s from.
185179 */
186- public Builder .Constraint destinationPathPatterns (String ... patterns ) {
187- return destinationPathPatterns (null , patterns );
188- }
189-
190- /**
191- * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances that
192- * match on {@code SimpMessageType.MESSAGE}. If no destination is found on the
193- * Message, then the Matcher returns false.
194- * @param patterns the patterns to create
195- * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher}
196- * from.
197- * @deprecated use {@link #destinationPathPatterns(String...)}
198- */
199- @ Deprecated
200180 public Builder .Constraint simpMessageDestMatchers (String ... patterns ) {
201181 return simpDestMatchers (SimpMessageType .MESSAGE , patterns );
202182 }
203183
204184 /**
205- * Allows the creation of a security {@link Constraint} applying to messages of
206- * the type {@code SimpMessageType.MESSAGE} whose destinations match the provided
207- * {@code patterns}.
208- * <p>
209- * The matching of each pattern is performed by a
210- * {@link PathPatternMessageMatcher}. If no destination is found on the
211- * {@code Message}, then each {@code Matcher} returns false.
212- * @param patterns the patterns to create {@link PathPatternMessageMatcher} from.
213- * @since 6.5
214- */
215- public Builder .Constraint simpTypeMessageDestinationPatterns (String ... patterns ) {
216- return destinationPathPatterns (SimpMessageType .MESSAGE , patterns );
217- }
218-
219- /**
220- * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances that
221- * match on {@code SimpMessageType.SUBSCRIBE}. If no destination is found on the
222- * Message, then the Matcher returns false.
223- * @param patterns the patterns to create
224- * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher}
225- * from.
226- * @deprecated use {@link #simpTypeSubscribeDestinationPatterns(String...)}
185+ * Maps a {@link List} of {@link SimpDestinationMessageMatcher} (or
186+ * {@link PathPatternMessageMatcher} if the application has configured a
187+ * {@link org.springframework.security.messaging.util.matcher.PathPatternMessageMatcherBuilderFactoryBean})
188+ * instances that match on {@code SimpMessageType.SUBSCRIBE}. If no destination is
189+ * found on the Message, then the Matcher returns false.
190+ * @param patterns the patterns to create {@code MessageMatcher}s from.
227191 */
228- @ Deprecated
229192 public Builder .Constraint simpSubscribeDestMatchers (String ... patterns ) {
230193 return simpDestMatchers (SimpMessageType .SUBSCRIBE , patterns );
231194 }
232195
233196 /**
234- * Allows the creation of a security {@link Constraint} applying to messages of
235- * the type {@code SimpMessageType.SUBSCRIBE} whose destinations match the
236- * provided {@code patterns}.
237- * <p>
238- * The matching of each pattern is performed by a
239- * {@link PathPatternMessageMatcher}. If no destination is found on the
240- * {@code Message}, then each {@code Matcher} returns false.
241- * @param patterns the patterns to create {@link PathPatternMessageMatcher} from.
242- * @since 6.5
243- */
244- public Builder .Constraint simpTypeSubscribeDestinationPatterns (String ... patterns ) {
245- return destinationPathPatterns (SimpMessageType .SUBSCRIBE , patterns );
246- }
247-
248- /**
249- * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances. If no
250- * destination is found on the Message, then the Matcher returns false.
197+ * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances, or
198+ * {@link PathPatternMessageMatcher} if the application has configured a
199+ * {@link org.springframework.security.messaging.util.matcher.PathPatternMessageMatcherBuilderFactoryBean}.
200+ * If no destination is found on the Message, then the Matcher returns false.
251201 * @param type the {@link SimpMessageType} to match on. If null, the
252202 * {@link SimpMessageType} is not considered for matching.
253- * @param patterns the patterns to create
254- * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher}
255- * from.
203+ * @param patterns the patterns to create {@code MessageMatcher}s from.
256204 * @return the {@link Builder.Constraint} that is associated to the
257205 * {@link MessageMatcher}
258- * @deprecated use {@link #destinationPathPatterns(String...)}
259206 */
260- @ Deprecated
261207 private Builder .Constraint simpDestMatchers (SimpMessageType type , String ... patterns ) {
262208 List <MessageMatcher <?>> matchers = new ArrayList <>(patterns .length );
263209 for (String pattern : patterns ) {
264- MessageMatcher <Object > matcher = new LazySimpDestinationMessageMatcher (pattern , type );
210+ MessageMatcher <Object > matcher = MessageMatcherFactory .usesPathPatterns ()
211+ ? MessageMatcherFactory .matcher (pattern , type )
212+ : new LazySimpDestinationMessageMatcher (pattern , type );
265213 matchers .add (matcher );
266214 }
267215 return new Builder .Constraint (matchers );
268216 }
269217
270- /**
271- * Allows the creation of a security {@link Constraint} applying to messages of
272- * the provided {@code type} whose destinations match the provided
273- * {@code patterns}.
274- * <p>
275- * The matching of each pattern is performed by a
276- * {@link PathPatternMessageMatcher}. If no destination is found on the
277- * {@code Message}, then each {@code Matcher} returns false.
278- * </p>
279- * @param type the {@link SimpMessageType} to match on. If null, the
280- * {@link SimpMessageType} is not considered for matching.
281- * @param patterns the patterns to create {@link PathPatternMessageMatcher} from.
282- * @return the {@link Builder.Constraint} that is associated to the
283- * {@link MessageMatcher}s
284- * @since 6.5
285- */
286- private Builder .Constraint destinationPathPatterns (SimpMessageType type , String ... patterns ) {
287- List <MessageMatcher <?>> matchers = new ArrayList <>(patterns .length );
288- for (String pattern : patterns ) {
289- MessageMatcher <Object > matcher = new LazySimpDestinationPatternMessageMatcher (pattern , type ,
290- this .useHttpPathSeparator );
291- matchers .add (matcher );
292- }
293- return new Builder .Constraint (matchers );
294- }
295-
296- /**
297- * Instruct this builder to match message destinations using the separator
298- * configured in
299- * {@link org.springframework.http.server.PathContainer.Options#MESSAGE_ROUTE}
300- */
301- public Builder messageRouteSeparator () {
302- this .useHttpPathSeparator = false ;
303- return this ;
304- }
305-
306218 /**
307219 * The {@link PathMatcher} to be used with the
308220 * {@link Builder#simpDestMatchers(String...)}. The default is to use the default
309221 * constructor of {@link AntPathMatcher}.
310222 * @param pathMatcher the {@link PathMatcher} to use. Cannot be null.
311223 * @return the {@link Builder} for further customization.
312- * @deprecated use {@link #messageRouteSeparator()} to alter the path separator
224+ * @deprecated
313225 */
314226 @ Deprecated
315227 public Builder simpDestPathMatcher (PathMatcher pathMatcher ) {
@@ -324,7 +236,7 @@ public Builder simpDestPathMatcher(PathMatcher pathMatcher) {
324236 * computation or lookup of the {@link PathMatcher}.
325237 * @param pathMatcher the {@link PathMatcher} to use. Cannot be null.
326238 * @return the {@link Builder} for further customization.
327- * @deprecated use {@link #messageRouteSeparator()} to alter the path separator
239+ * @deprecated
328240 */
329241 @ Deprecated
330242 public Builder simpDestPathMatcher (Supplier <PathMatcher > pathMatcher ) {
@@ -513,40 +425,6 @@ Map<String, String> extractPathVariables(Message<?> message) {
513425
514426 }
515427
516- private static final class LazySimpDestinationPatternMessageMatcher implements MessageMatcher <Object > {
517-
518- private final Supplier <PathPatternMessageMatcher > delegate ;
519-
520- private LazySimpDestinationPatternMessageMatcher (String pattern , SimpMessageType type ,
521- boolean useHttpPathSeparator ) {
522- this .delegate = SingletonSupplier .of (() -> {
523- PathPatternParser dotSeparatedPathParser = new PathPatternParser ();
524- dotSeparatedPathParser .setPathOptions (PathContainer .Options .MESSAGE_ROUTE );
525- PathPatternMessageMatcher .Builder builder = (useHttpPathSeparator )
526- ? PathPatternMessageMatcher .withDefaults ()
527- : PathPatternMessageMatcher .withPathPatternParser (dotSeparatedPathParser );
528- if (type == null ) {
529- return builder .matcher (pattern );
530- }
531- if (SimpMessageType .MESSAGE == type || SimpMessageType .SUBSCRIBE == type ) {
532- return builder .matcher (pattern , type );
533- }
534- throw new IllegalStateException (type + " is not supported since it does not have a destination" );
535- });
536- }
537-
538- @ Override
539- public boolean matches (Message <?> message ) {
540- return this .delegate .get ().matches (message );
541- }
542-
543- Map <String , String > extractPathVariables (Message <?> message ) {
544- MatchResult matchResult = this .delegate .get ().matcher (message );
545- return matchResult .getVariables ();
546- }
547-
548- }
549-
550428 }
551429
552430 private static final class Entry <T > {
0 commit comments