16
16
17
17
package org .springframework .security .authorization ;
18
18
19
+ import java .util .ArrayList ;
20
+ import java .util .List ;
21
+
19
22
import org .jspecify .annotations .Nullable ;
20
23
21
24
import org .springframework .security .access .hierarchicalroles .NullRoleHierarchy ;
22
25
import org .springframework .security .access .hierarchicalroles .RoleHierarchy ;
23
26
import org .springframework .security .authentication .AuthenticationTrustResolver ;
24
27
import org .springframework .security .authentication .AuthenticationTrustResolverImpl ;
25
28
import org .springframework .util .Assert ;
29
+ import org .springframework .util .CollectionUtils ;
26
30
27
31
/**
28
32
* A factory for creating different kinds of {@link AuthorizationManager} instances.
29
33
*
30
34
* @param <T> the type of object that the authorization check is being done on
31
35
* @author Steve Riesenberg
32
36
* @author Andrey Litvitski
37
+ * @author Rob Winch
33
38
* @since 7.0
34
39
*/
35
40
public final class DefaultAuthorizationManagerFactory <T extends @ Nullable Object >
@@ -41,7 +46,7 @@ public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object
41
46
42
47
private String rolePrefix = "ROLE_" ;
43
48
44
- private String [] requiredAuthorities = new String [ 0 ] ;
49
+ private @ Nullable AuthorizationManager < T > additionalAuthorization ;
45
50
46
51
/**
47
52
* Sets the {@link AuthenticationTrustResolver} used to check the user's
@@ -73,32 +78,29 @@ public void setRolePrefix(String rolePrefix) {
73
78
}
74
79
75
80
/**
76
- * Sets authorities required for authorization managers that apply to authenticated
77
- * users.
78
- * <p>
79
- * Does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
80
- * <p>
81
- * Evaluated with the configured {@link RoleHierarchy}.
82
- * @param requiredAuthorities the required authorities (must not be {@code null})
83
- */
84
- public void setRequiredAuthorities (String [] requiredAuthorities ) {
85
- Assert .notNull (requiredAuthorities , "requiredAuthorities cannot be null" );
86
- this .requiredAuthorities = requiredAuthorities ;
87
- }
88
-
89
- /**
90
- * Creates a factory that requires the given authorities for authorization managers
91
- * that apply to authenticated users.
81
+ * Sets additional authorization to be applied to the returned
82
+ * {@link AuthorizationManager} for the following methods:
83
+ *
84
+ * <ul>
85
+ * <li>{@link #hasRole(String)}</li>
86
+ * <li>{@link #hasAnyRole(String...)}</li>
87
+ * <li>{@link #hasAllRoles(String...)}</li>
88
+ * <li>{@link #hasAuthority(String)}</li>
89
+ * <li>{@link #hasAnyAuthority(String...)}</li>
90
+ * <li>{@link #hasAllAuthorities(String...)}</li>
91
+ * <li>{@link #authenticated()}</li>
92
+ * <li>{@link #fullyAuthenticated()}</li>
93
+ * <li>{@link #rememberMe()}</li>
94
+ * </ul>
95
+ *
92
96
* <p>
93
- * Does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
94
- * @param authorities the required authorities
95
- * @param <T> the secured object type
96
- * @return a factory configured with the required authorities
97
+ * This does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
98
+ * </p>
99
+ * @param additionalAuthorization the {@link AuthorizationManager} to be applied.
100
+ * Default is null (no additional authorization).
97
101
*/
98
- public static <T > AuthorizationManagerFactory <T > withAuthorities (String ... authorities ) {
99
- DefaultAuthorizationManagerFactory <T > factory = new DefaultAuthorizationManagerFactory <>();
100
- factory .setRequiredAuthorities (authorities );
101
- return factory ;
102
+ public void setAdditionalAuthorization (@ Nullable AuthorizationManager <T > additionalAuthorization ) {
103
+ this .additionalAuthorization = additionalAuthorization ;
102
104
}
103
105
104
106
@ Override
@@ -108,76 +110,140 @@ public AuthorizationManager<T> hasRole(String role) {
108
110
109
111
@ Override
110
112
public AuthorizationManager <T > hasAnyRole (String ... roles ) {
111
- return withRequiredAuthorities (
112
- withRoleHierarchy (AuthorityAuthorizationManager .hasAnyRole (this .rolePrefix , roles )));
113
+ return createManager (AuthorityAuthorizationManager .hasAnyRole (this .rolePrefix , roles ));
113
114
}
114
115
115
116
@ Override
116
117
public AuthorizationManager <T > hasAllRoles (String ... roles ) {
117
- return withRequiredAuthorities (withRoleHierarchy (
118
- AllAuthoritiesAuthorizationManager .hasAllPrefixedAuthorities (this .rolePrefix , roles )));
118
+ return createManager (AllAuthoritiesAuthorizationManager .hasAllPrefixedAuthorities (this .rolePrefix , roles ));
119
119
}
120
120
121
121
@ Override
122
122
public AuthorizationManager <T > hasAuthority (String authority ) {
123
- return withRequiredAuthorities ( withRoleHierarchy ( AuthorityAuthorizationManager .hasAuthority (authority ) ));
123
+ return createManager ( AuthorityAuthorizationManager .hasAuthority (authority ));
124
124
}
125
125
126
126
@ Override
127
127
public AuthorizationManager <T > hasAnyAuthority (String ... authorities ) {
128
- return withRequiredAuthorities ( withRoleHierarchy ( AuthorityAuthorizationManager .hasAnyAuthority (authorities ) ));
128
+ return createManager ( AuthorityAuthorizationManager .hasAnyAuthority (authorities ));
129
129
}
130
130
131
131
@ Override
132
132
public AuthorizationManager <T > hasAllAuthorities (String ... authorities ) {
133
- return withRequiredAuthorities (
134
- withRoleHierarchy (AllAuthoritiesAuthorizationManager .hasAllAuthorities (authorities )));
133
+ return createManager (AllAuthoritiesAuthorizationManager .hasAllAuthorities (authorities ));
135
134
}
136
135
137
136
@ Override
138
137
public AuthorizationManager <T > authenticated () {
139
- return withRequiredAuthorities ( withTrustResolver ( AuthenticatedAuthorizationManager .authenticated () ));
138
+ return createManager ( AuthenticatedAuthorizationManager .authenticated ());
140
139
}
141
140
142
141
@ Override
143
142
public AuthorizationManager <T > fullyAuthenticated () {
144
- return withRequiredAuthorities ( withTrustResolver ( AuthenticatedAuthorizationManager .fullyAuthenticated () ));
143
+ return createManager ( AuthenticatedAuthorizationManager .fullyAuthenticated ());
145
144
}
146
145
147
146
@ Override
148
147
public AuthorizationManager <T > rememberMe () {
149
- return withRequiredAuthorities ( withTrustResolver ( AuthenticatedAuthorizationManager .rememberMe () ));
148
+ return createManager ( AuthenticatedAuthorizationManager .rememberMe ());
150
149
}
151
150
152
151
@ Override
153
152
public AuthorizationManager <T > anonymous () {
154
- return withTrustResolver (AuthenticatedAuthorizationManager .anonymous ());
153
+ return createManager (AuthenticatedAuthorizationManager .anonymous ());
155
154
}
156
155
157
- private AuthorityAuthorizationManager <T > withRoleHierarchy (AuthorityAuthorizationManager <T > authorizationManager ) {
156
+ /**
157
+ * Creates a {@link Builder} that helps build an {@link AuthorizationManager} to set
158
+ * on {@link #setAdditionalAuthorization(AuthorizationManager)} for common scenarios.
159
+ * <p>
160
+ * Does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
161
+ * @param <T> the secured object type
162
+ * @return a factory configured with the required authorities
163
+ */
164
+ public static <T > Builder <T > builder () {
165
+ return new Builder <>();
166
+ }
167
+
168
+ private AuthorizationManager <T > createManager (AuthorityAuthorizationManager <T > authorizationManager ) {
158
169
authorizationManager .setRoleHierarchy (this .roleHierarchy );
159
- return authorizationManager ;
170
+ return withAdditionalAuthorization ( authorizationManager ) ;
160
171
}
161
172
162
- private AllAuthoritiesAuthorizationManager <T > withRoleHierarchy (
163
- AllAuthoritiesAuthorizationManager <T > authorizationManager ) {
173
+ private AuthorizationManager <T > createManager (AllAuthoritiesAuthorizationManager <T > authorizationManager ) {
164
174
authorizationManager .setRoleHierarchy (this .roleHierarchy );
165
- return authorizationManager ;
175
+ return withAdditionalAuthorization ( authorizationManager ) ;
166
176
}
167
177
168
- private AuthenticatedAuthorizationManager <T > withTrustResolver (
169
- AuthenticatedAuthorizationManager <T > authorizationManager ) {
178
+ private AuthorizationManager <T > createManager (AuthenticatedAuthorizationManager <T > authorizationManager ) {
170
179
authorizationManager .setTrustResolver (this .trustResolver );
171
- return authorizationManager ;
180
+ return withAdditionalAuthorization ( authorizationManager ) ;
172
181
}
173
182
174
- private AuthorizationManager <T > withRequiredAuthorities (AuthorizationManager <T > manager ) {
175
- if (this .requiredAuthorities == null || this . requiredAuthorities . length == 0 ) {
183
+ private AuthorizationManager <T > withAdditionalAuthorization (AuthorizationManager <T > manager ) {
184
+ if (this .additionalAuthorization == null ) {
176
185
return manager ;
177
186
}
178
- AuthorizationManager <T > required = withRoleHierarchy (
179
- AllAuthoritiesAuthorizationManager .hasAllAuthorities (this .requiredAuthorities ));
180
- return AuthorizationManagers .allOf (new AuthorizationDecision (false ), manager , required );
187
+ return AuthorizationManagers .allOf (new AuthorizationDecision (false ), this .additionalAuthorization , manager );
188
+ }
189
+
190
+ /**
191
+ * A builder that allows creating {@link DefaultAuthorizationManagerFactory} with
192
+ * additional authorization for common scenarios.
193
+ *
194
+ * @param <T> the type for the {@link DefaultAuthorizationManagerFactory}
195
+ * @author Rob Winch
196
+ */
197
+ public static final class Builder <T > {
198
+
199
+ private final List <String > additionalAuthorities = new ArrayList <>();
200
+
201
+ private RoleHierarchy roleHierarchy = new NullRoleHierarchy ();
202
+
203
+ /**
204
+ * Add additional authorities that will be required.
205
+ * @param additionalAuthorities the additional authorities.
206
+ * @return the {@link Builder} to further customize.
207
+ */
208
+ public Builder <T > requireAdditionalAuthorities (String ... additionalAuthorities ) {
209
+ Assert .notEmpty (additionalAuthorities , "additionalAuthorities cannot be empty" );
210
+ for (String additionalAuthority : additionalAuthorities ) {
211
+ this .additionalAuthorities .add (additionalAuthority );
212
+ }
213
+ return this ;
214
+ }
215
+
216
+ /**
217
+ * The {@link RoleHierarchy} to use.
218
+ * @param roleHierarchy the non-null {@link RoleHierarchy} to use. Default is
219
+ * {@link NullRoleHierarchy}.
220
+ * @return the Builder to further customize.
221
+ */
222
+ public Builder <T > roleHierarchy (RoleHierarchy roleHierarchy ) {
223
+ Assert .notNull (roleHierarchy , "roleHierarchy cannot be null" );
224
+ this .roleHierarchy = roleHierarchy ;
225
+ return this ;
226
+ }
227
+
228
+ /**
229
+ * Builds a {@link DefaultAuthorizationManagerFactory} that has the
230
+ * {@link #setAdditionalAuthorization(AuthorizationManager)} set.
231
+ * @return the {@link DefaultAuthorizationManagerFactory}.
232
+ */
233
+ public DefaultAuthorizationManagerFactory <T > build () {
234
+ Assert .state (!CollectionUtils .isEmpty (this .additionalAuthorities ), "additionalAuthorities cannot be empty" );
235
+ DefaultAuthorizationManagerFactory <T > result = new DefaultAuthorizationManagerFactory <>();
236
+ AllAuthoritiesAuthorizationManager <T > additionalChecks = AllAuthoritiesAuthorizationManager
237
+ .hasAllAuthorities (this .additionalAuthorities );
238
+ result .setRoleHierarchy (this .roleHierarchy );
239
+ additionalChecks .setRoleHierarchy (this .roleHierarchy );
240
+ result .setAdditionalAuthorization (additionalChecks );
241
+ return result ;
242
+ }
243
+
244
+ private Builder () {
245
+ }
246
+
181
247
}
182
248
183
249
}
0 commit comments