Skip to content

Commit 68742e1

Browse files
committed
Support Automatically Checking for Required Authorities in Authorization Rules
Closes: spring-projectsgh-17900 Signed-off-by: Andrey Litvitski <[email protected]>
1 parent a63e87d commit 68742e1

File tree

1 file changed

+52
-8
lines changed

1 file changed

+52
-8
lines changed

core/src/main/java/org/springframework/security/authorization/DefaultAuthorizationManagerFactory.java

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*
3030
* @param <T> the type of object that the authorization check is being done on
3131
* @author Steve Riesenberg
32+
* @author Andrey Litvitski
3233
* @since 7.0
3334
*/
3435
public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object>
@@ -40,6 +41,8 @@ public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object
4041

4142
private String rolePrefix = "ROLE_";
4243

44+
private String[] requiredAuthorities = new String[0];
45+
4346
/**
4447
* Sets the {@link AuthenticationTrustResolver} used to check the user's
4548
* authentication.
@@ -69,49 +72,81 @@ public void setRolePrefix(String rolePrefix) {
6972
this.rolePrefix = rolePrefix;
7073
}
7174

75+
/**
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.
92+
* <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+
*/
98+
public static <T> AuthorizationManagerFactory<T> withAuthorities(String... authorities) {
99+
DefaultAuthorizationManagerFactory<T> factory = new DefaultAuthorizationManagerFactory<>();
100+
factory.setRequiredAuthorities(authorities);
101+
return factory;
102+
}
103+
72104
@Override
73105
public AuthorizationManager<T> hasRole(String role) {
74106
return hasAnyRole(role);
75107
}
76108

77109
@Override
78110
public AuthorizationManager<T> hasAnyRole(String... roles) {
79-
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, roles));
111+
return withRequiredAuthorities(
112+
withRoleHierarchy(AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, roles)));
80113
}
81114

82115
@Override
83116
public AuthorizationManager<T> hasAllRoles(String... roles) {
84-
return withRoleHierarchy(AllAuthoritiesAuthorizationManager.hasAllPrefixedAuthorities(this.rolePrefix, roles));
117+
return withRequiredAuthorities(withRoleHierarchy(
118+
AllAuthoritiesAuthorizationManager.hasAllPrefixedAuthorities(this.rolePrefix, roles)));
85119
}
86120

87121
@Override
88122
public AuthorizationManager<T> hasAuthority(String authority) {
89-
return withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority));
123+
return withRequiredAuthorities(withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority)));
90124
}
91125

92126
@Override
93127
public AuthorizationManager<T> hasAnyAuthority(String... authorities) {
94-
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities));
128+
return withRequiredAuthorities(withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities)));
95129
}
96130

97131
@Override
98132
public AuthorizationManager<T> hasAllAuthorities(String... authorities) {
99-
return withRoleHierarchy(AllAuthoritiesAuthorizationManager.hasAllAuthorities(authorities));
133+
return withRequiredAuthorities(
134+
withRoleHierarchy(AllAuthoritiesAuthorizationManager.hasAllAuthorities(authorities)));
100135
}
101136

102137
@Override
103138
public AuthorizationManager<T> authenticated() {
104-
return withTrustResolver(AuthenticatedAuthorizationManager.authenticated());
139+
return withRequiredAuthorities(withTrustResolver(AuthenticatedAuthorizationManager.authenticated()));
105140
}
106141

107142
@Override
108143
public AuthorizationManager<T> fullyAuthenticated() {
109-
return withTrustResolver(AuthenticatedAuthorizationManager.fullyAuthenticated());
144+
return withRequiredAuthorities(withTrustResolver(AuthenticatedAuthorizationManager.fullyAuthenticated()));
110145
}
111146

112147
@Override
113148
public AuthorizationManager<T> rememberMe() {
114-
return withTrustResolver(AuthenticatedAuthorizationManager.rememberMe());
149+
return withRequiredAuthorities(withTrustResolver(AuthenticatedAuthorizationManager.rememberMe()));
115150
}
116151

117152
@Override
@@ -136,4 +171,13 @@ private AuthenticatedAuthorizationManager<T> withTrustResolver(
136171
return authorizationManager;
137172
}
138173

174+
private AuthorizationManager<T> withRequiredAuthorities(AuthorizationManager<T> manager) {
175+
if (this.requiredAuthorities == null || this.requiredAuthorities.length == 0) {
176+
return manager;
177+
}
178+
AuthorizationManager<T> required = withRoleHierarchy(
179+
AllAuthoritiesAuthorizationManager.hasAllAuthorities(this.requiredAuthorities));
180+
return AuthorizationManagers.allOf(new AuthorizationDecision(false), manager, required);
181+
}
182+
139183
}

0 commit comments

Comments
 (0)