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