11/*
2- * Copyright 2002-2022 the original author or authors.
2+ * Copyright 2002-2023 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
2626import org .apache .commons .logging .LogFactory ;
2727
2828import org .springframework .core .log .LogMessage ;
29+ import org .springframework .security .authorization .AuthenticatedAuthorizationManager ;
30+ import org .springframework .security .authorization .AuthorityAuthorizationManager ;
2931import org .springframework .security .authorization .AuthorizationDecision ;
3032import org .springframework .security .authorization .AuthorizationManager ;
3133import org .springframework .security .core .Authentication ;
34+ import org .springframework .security .web .util .matcher .AnyRequestMatcher ;
3235import org .springframework .security .web .util .matcher .RequestMatcher ;
3336import org .springframework .security .web .util .matcher .RequestMatcher .MatchResult ;
3437import org .springframework .security .web .util .matcher .RequestMatcherEntry ;
@@ -102,6 +105,8 @@ public static Builder builder() {
102105 */
103106 public static final class Builder {
104107
108+ private boolean anyRequestConfigured ;
109+
105110 private final List <RequestMatcherEntry <AuthorizationManager <RequestAuthorizationContext >>> mappings = new ArrayList <>();
106111
107112 /**
@@ -111,6 +116,7 @@ public static final class Builder {
111116 * @return the {@link Builder} for further customizations
112117 */
113118 public Builder add (RequestMatcher matcher , AuthorizationManager <RequestAuthorizationContext > manager ) {
119+ Assert .state (!this .anyRequestConfigured , "Can't add mappings after anyRequest" );
114120 Assert .notNull (matcher , "matcher cannot be null" );
115121 Assert .notNull (manager , "manager cannot be null" );
116122 this .mappings .add (new RequestMatcherEntry <>(matcher , manager ));
@@ -127,11 +133,34 @@ public Builder add(RequestMatcher matcher, AuthorizationManager<RequestAuthoriza
127133 */
128134 public Builder mappings (
129135 Consumer <List <RequestMatcherEntry <AuthorizationManager <RequestAuthorizationContext >>>> mappingsConsumer ) {
136+ Assert .state (!this .anyRequestConfigured , "Can't configure mappings after anyRequest" );
130137 Assert .notNull (mappingsConsumer , "mappingsConsumer cannot be null" );
131138 mappingsConsumer .accept (this .mappings );
132139 return this ;
133140 }
134141
142+ /**
143+ * Maps any request.
144+ * @return the {@link AuthorizedUrl} for further customizations
145+ * @since 6.2
146+ */
147+ public AuthorizedUrl anyRequest () {
148+ Assert .state (!this .anyRequestConfigured , "Can't configure anyRequest after itself" );
149+ this .anyRequestConfigured = true ;
150+ return new AuthorizedUrl (AnyRequestMatcher .INSTANCE );
151+ }
152+
153+ /**
154+ * Maps {@link RequestMatcher}s to {@link AuthorizationManager}.
155+ * @param matchers the {@link RequestMatcher}s to map
156+ * @return the {@link AuthorizedUrl} for further customizations
157+ * @since 6.2
158+ */
159+ public AuthorizedUrl requestMatchers (RequestMatcher ... matchers ) {
160+ Assert .state (!this .anyRequestConfigured , "Can't configure requestMatchers after anyRequest" );
161+ return new AuthorizedUrl (matchers );
162+ }
163+
135164 /**
136165 * Creates a {@link RequestMatcherDelegatingAuthorizationManager} instance.
137166 * @return the {@link RequestMatcherDelegatingAuthorizationManager} instance
@@ -140,6 +169,123 @@ public RequestMatcherDelegatingAuthorizationManager build() {
140169 return new RequestMatcherDelegatingAuthorizationManager (this .mappings );
141170 }
142171
172+ /**
173+ * An object that allows configuring the {@link AuthorizationManager} for
174+ * {@link RequestMatcher}s.
175+ *
176+ * @author Evgeniy Cheban
177+ * @since 6.2
178+ */
179+ public final class AuthorizedUrl {
180+
181+ private final List <RequestMatcher > matchers ;
182+
183+ private AuthorizedUrl (RequestMatcher ... matchers ) {
184+ this (List .of (matchers ));
185+ }
186+
187+ private AuthorizedUrl (List <RequestMatcher > matchers ) {
188+ this .matchers = matchers ;
189+ }
190+
191+ /**
192+ * Specify that URLs are allowed by anyone.
193+ * @return the {@link Builder} for further customizations
194+ */
195+ public Builder permitAll () {
196+ return access ((a , o ) -> new AuthorizationDecision (true ));
197+ }
198+
199+ /**
200+ * Specify that URLs are not allowed by anyone.
201+ * @return the {@link Builder} for further customizations
202+ */
203+ public Builder denyAll () {
204+ return access ((a , o ) -> new AuthorizationDecision (false ));
205+ }
206+
207+ /**
208+ * Specify that URLs are allowed by any authenticated user.
209+ * @return the {@link Builder} for further customizations
210+ */
211+ public Builder authenticated () {
212+ return access (AuthenticatedAuthorizationManager .authenticated ());
213+ }
214+
215+ /**
216+ * Specify that URLs are allowed by users who have authenticated and were not
217+ * "remembered".
218+ * @return the {@link Builder} for further customization
219+ */
220+ public Builder fullyAuthenticated () {
221+ return access (AuthenticatedAuthorizationManager .fullyAuthenticated ());
222+ }
223+
224+ /**
225+ * Specify that URLs are allowed by users that have been remembered.
226+ * @return the {@link Builder} for further customization
227+ */
228+ public Builder rememberMe () {
229+ return access (AuthenticatedAuthorizationManager .rememberMe ());
230+ }
231+
232+ /**
233+ * Specify that URLs are allowed by anonymous users.
234+ * @return the {@link Builder} for further customization
235+ */
236+ public Builder anonymous () {
237+ return access (AuthenticatedAuthorizationManager .anonymous ());
238+ }
239+
240+ /**
241+ * Specifies a user requires a role.
242+ * @param role the role that should be required which is prepended with ROLE_
243+ * automatically (i.e. USER, ADMIN, etc). It should not start with ROLE_
244+ * @return {@link Builder} for further customizations
245+ */
246+ public Builder hasRole (String role ) {
247+ return access (AuthorityAuthorizationManager .hasRole (role ));
248+ }
249+
250+ /**
251+ * Specifies that a user requires one of many roles.
252+ * @param roles the roles that the user should have at least one of (i.e.
253+ * ADMIN, USER, etc). Each role should not start with ROLE_ since it is
254+ * automatically prepended already
255+ * @return the {@link Builder} for further customizations
256+ */
257+ public Builder hasAnyRole (String ... roles ) {
258+ return access (AuthorityAuthorizationManager .hasAnyRole (roles ));
259+ }
260+
261+ /**
262+ * Specifies a user requires an authority.
263+ * @param authority the authority that should be required
264+ * @return the {@link Builder} for further customizations
265+ */
266+ public Builder hasAuthority (String authority ) {
267+ return access (AuthorityAuthorizationManager .hasAuthority (authority ));
268+ }
269+
270+ /**
271+ * Specifies that a user requires one of many authorities.
272+ * @param authorities the authorities that the user should have at least one
273+ * of (i.e. ROLE_USER, ROLE_ADMIN, etc)
274+ * @return the {@link Builder} for further customizations
275+ */
276+ public Builder hasAnyAuthority (String ... authorities ) {
277+ return access (AuthorityAuthorizationManager .hasAnyAuthority (authorities ));
278+ }
279+
280+ private Builder access (AuthorizationManager <RequestAuthorizationContext > manager ) {
281+ for (RequestMatcher matcher : this .matchers ) {
282+ Builder .this .mappings .add (new RequestMatcherEntry <>(matcher , manager ));
283+ }
284+ return Builder .this ;
285+ }
286+
287+ }
288+
143289 }
144290
145291}
0 commit comments