1
1
/*
2
- * Copyright 2002-2022 the original author or authors.
2
+ * Copyright 2002-2023 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
26
26
import org .apache .commons .logging .LogFactory ;
27
27
28
28
import org .springframework .core .log .LogMessage ;
29
+ import org .springframework .security .authorization .AuthenticatedAuthorizationManager ;
30
+ import org .springframework .security .authorization .AuthorityAuthorizationManager ;
29
31
import org .springframework .security .authorization .AuthorizationDecision ;
30
32
import org .springframework .security .authorization .AuthorizationManager ;
31
33
import org .springframework .security .core .Authentication ;
34
+ import org .springframework .security .web .util .matcher .AnyRequestMatcher ;
32
35
import org .springframework .security .web .util .matcher .RequestMatcher ;
33
36
import org .springframework .security .web .util .matcher .RequestMatcher .MatchResult ;
34
37
import org .springframework .security .web .util .matcher .RequestMatcherEntry ;
@@ -102,6 +105,8 @@ public static Builder builder() {
102
105
*/
103
106
public static final class Builder {
104
107
108
+ private boolean anyRequestConfigured ;
109
+
105
110
private final List <RequestMatcherEntry <AuthorizationManager <RequestAuthorizationContext >>> mappings = new ArrayList <>();
106
111
107
112
/**
@@ -111,6 +116,7 @@ public static final class Builder {
111
116
* @return the {@link Builder} for further customizations
112
117
*/
113
118
public Builder add (RequestMatcher matcher , AuthorizationManager <RequestAuthorizationContext > manager ) {
119
+ Assert .state (!this .anyRequestConfigured , "Can't add mappings after anyRequest" );
114
120
Assert .notNull (matcher , "matcher cannot be null" );
115
121
Assert .notNull (manager , "manager cannot be null" );
116
122
this .mappings .add (new RequestMatcherEntry <>(matcher , manager ));
@@ -127,11 +133,34 @@ public Builder add(RequestMatcher matcher, AuthorizationManager<RequestAuthoriza
127
133
*/
128
134
public Builder mappings (
129
135
Consumer <List <RequestMatcherEntry <AuthorizationManager <RequestAuthorizationContext >>>> mappingsConsumer ) {
136
+ Assert .state (!this .anyRequestConfigured , "Can't configure mappings after anyRequest" );
130
137
Assert .notNull (mappingsConsumer , "mappingsConsumer cannot be null" );
131
138
mappingsConsumer .accept (this .mappings );
132
139
return this ;
133
140
}
134
141
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
+
135
164
/**
136
165
* Creates a {@link RequestMatcherDelegatingAuthorizationManager} instance.
137
166
* @return the {@link RequestMatcherDelegatingAuthorizationManager} instance
@@ -140,6 +169,123 @@ public RequestMatcherDelegatingAuthorizationManager build() {
140
169
return new RequestMatcherDelegatingAuthorizationManager (this .mappings );
141
170
}
142
171
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
+
143
289
}
144
290
145
291
}
0 commit comments