Skip to content

Commit 9ce5a76

Browse files
committed
Polish AuthorizationManager#authorize
Issue gh-14843
1 parent e764492 commit 9ce5a76

20 files changed

+160
-73
lines changed

config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,8 @@ private boolean checkLoginPageIsPublic(List<Filter> filters, FilterInvocation lo
221221
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
222222
.getAuthorizationManager();
223223
try {
224-
AuthorizationResult decision = authorizationManager.authorize(() -> TEST,
225-
loginRequest.getHttpRequest());
226-
return decision != null && decision.isGranted();
224+
AuthorizationResult result = authorizationManager.authorize(() -> TEST, loginRequest.getHttpRequest());
225+
return result != null && result.isGranted();
227226
}
228227
catch (Exception ex) {
229228
return false;
@@ -253,9 +252,8 @@ private Supplier<Boolean> deriveAnonymousCheck(List<Filter> filters, FilterInvoc
253252
return () -> {
254253
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
255254
.getAuthorizationManager();
256-
AuthorizationResult decision = authorizationManager.authorize(() -> token,
257-
loginRequest.getHttpRequest());
258-
return decision != null && decision.isGranted();
255+
AuthorizationResult result = authorizationManager.authorize(() -> token, loginRequest.getHttpRequest());
256+
return result != null && result.isGranted();
259257
};
260258
}
261259
return () -> true;

config/src/main/java/org/springframework/security/config/method/PointcutDelegatingAuthorizationManager.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.aop.support.AopUtils;
2626
import org.springframework.security.authorization.AuthorizationDecision;
2727
import org.springframework.security.authorization.AuthorizationManager;
28+
import org.springframework.security.authorization.AuthorizationResult;
2829
import org.springframework.security.core.Authentication;
2930

3031
class PointcutDelegatingAuthorizationManager implements AuthorizationManager<MethodInvocation> {
@@ -37,11 +38,24 @@ class PointcutDelegatingAuthorizationManager implements AuthorizationManager<Met
3738

3839
@Override
3940
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation object) {
41+
AuthorizationResult result = authorize(authentication, object);
42+
if (result == null) {
43+
return null;
44+
}
45+
if (result instanceof AuthorizationDecision decision) {
46+
return decision;
47+
}
48+
throw new IllegalArgumentException(
49+
"Please either call authorize or ensure that the returned result is of type AuthorizationDecision");
50+
}
51+
52+
@Override
53+
public AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation object) {
4054
for (Map.Entry<Pointcut, AuthorizationManager<MethodInvocation>> entry : this.managers.entrySet()) {
4155
Class<?> targetClass = (object.getThis() != null) ? AopUtils.getTargetClass(object.getThis()) : null;
4256
if (entry.getKey().getClassFilter().matches(targetClass)
4357
&& entry.getKey().getMethodMatcher().matches(object.getMethod(), targetClass)) {
44-
return entry.getValue().check(authentication, object);
58+
return entry.getValue().authorize(authentication, object);
4559
}
4660
}
4761
return new AuthorizationDecision(false);

config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ public void transactionalAuthorizationManagerMethodsShouldBeSecured() {
168168

169169
@Test
170170
public void targetCustomAuthorizationManagerUsed() {
171+
given(this.mockAuthorizationManager.authorize(any(), any())).willCallRealMethod();
171172
given(this.mockAuthorizationManager.check(any(), any())).willReturn(new AuthorizationDecision(true));
172173
this.targetCustomAuthorizationManager.doSomething();
173174
verify(this.mockAuthorizationManager).check(any(), any());

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

+2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ private static String[] toNamedRolesArray(String rolePrefix, String[] roles) {
139139
* @param authentication the {@link Supplier} of the {@link Authentication} to check
140140
* @param object the {@link T} object to check
141141
* @return an {@link AuthorizationDecision}
142+
* @deprecated please use {@link #authorize(Supplier, Object)} instead
142143
*/
144+
@Deprecated
143145
@Override
144146
public AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
145147
return this.delegate.check(authentication, this.authorities);

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

+52-30
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.List;
21+
import java.util.function.Supplier;
22+
23+
import org.springframework.security.core.Authentication;
2124

2225
/**
2326
* A factory class to create an {@link AuthorizationManager} instances.
@@ -55,22 +58,22 @@ public static <T> AuthorizationManager<T> anyOf(AuthorizationManager<T>... manag
5558
@SafeVarargs
5659
public static <T> AuthorizationManager<T> anyOf(AuthorizationDecision allAbstainDefaultDecision,
5760
AuthorizationManager<T>... managers) {
58-
return (authentication, object) -> {
59-
List<AuthorizationDecision> decisions = new ArrayList<>();
61+
return (AuthorizationManagerCheckAdapter<T>) (authentication, object) -> {
62+
List<AuthorizationResult> results = new ArrayList<>();
6063
for (AuthorizationManager<T> manager : managers) {
61-
AuthorizationDecision decision = manager.check(authentication, object);
62-
if (decision == null) {
64+
AuthorizationResult result = manager.authorize(authentication, object);
65+
if (result == null) {
6366
continue;
6467
}
65-
if (decision.isGranted()) {
66-
return decision;
68+
if (result.isGranted()) {
69+
return result;
6770
}
68-
decisions.add(decision);
71+
results.add(result);
6972
}
70-
if (decisions.isEmpty()) {
73+
if (results.isEmpty()) {
7174
return allAbstainDefaultDecision;
7275
}
73-
return new CompositeAuthorizationDecision(false, decisions);
76+
return new CompositeAuthorizationDecision(false, results);
7477
};
7578
}
7679

@@ -101,22 +104,22 @@ public static <T> AuthorizationManager<T> allOf(AuthorizationManager<T>... manag
101104
@SafeVarargs
102105
public static <T> AuthorizationManager<T> allOf(AuthorizationDecision allAbstainDefaultDecision,
103106
AuthorizationManager<T>... managers) {
104-
return (authentication, object) -> {
105-
List<AuthorizationDecision> decisions = new ArrayList<>();
107+
return (AuthorizationManagerCheckAdapter<T>) (authentication, object) -> {
108+
List<AuthorizationResult> results = new ArrayList<>();
106109
for (AuthorizationManager<T> manager : managers) {
107-
AuthorizationDecision decision = manager.check(authentication, object);
108-
if (decision == null) {
110+
AuthorizationResult result = manager.authorize(authentication, object);
111+
if (result == null) {
109112
continue;
110113
}
111-
if (!decision.isGranted()) {
112-
return decision;
114+
if (!result.isGranted()) {
115+
return result;
113116
}
114-
decisions.add(decision);
117+
results.add(result);
115118
}
116-
if (decisions.isEmpty()) {
119+
if (results.isEmpty()) {
117120
return allAbstainDefaultDecision;
118121
}
119-
return new CompositeAuthorizationDecision(true, decisions);
122+
return new CompositeAuthorizationDecision(true, results);
120123
};
121124
}
122125

@@ -131,11 +134,11 @@ public static <T> AuthorizationManager<T> allOf(AuthorizationDecision allAbstain
131134
*/
132135
public static <T> AuthorizationManager<T> not(AuthorizationManager<T> manager) {
133136
return (authentication, object) -> {
134-
AuthorizationDecision decision = manager.check(authentication, object);
135-
if (decision == null) {
137+
AuthorizationResult result = manager.authorize(authentication, object);
138+
if (result == null) {
136139
return null;
137140
}
138-
return new NotAuthorizationDecision(decision);
141+
return new NotAuthorizationDecision(result);
139142
};
140143
}
141144

@@ -144,34 +147,53 @@ private AuthorizationManagers() {
144147

145148
private static final class CompositeAuthorizationDecision extends AuthorizationDecision {
146149

147-
private final List<AuthorizationDecision> decisions;
150+
private final List<AuthorizationResult> results;
148151

149-
private CompositeAuthorizationDecision(boolean granted, List<AuthorizationDecision> decisions) {
152+
private CompositeAuthorizationDecision(boolean granted, List<AuthorizationResult> results) {
150153
super(granted);
151-
this.decisions = decisions;
154+
this.results = results;
152155
}
153156

154157
@Override
155158
public String toString() {
156-
return "CompositeAuthorizationDecision [decisions=" + this.decisions + ']';
159+
return "CompositeAuthorizationDecision [results=" + this.results + ']';
157160
}
158161

159162
}
160163

161164
private static final class NotAuthorizationDecision extends AuthorizationDecision {
162165

163-
private final AuthorizationDecision decision;
166+
private final AuthorizationResult result;
164167

165-
private NotAuthorizationDecision(AuthorizationDecision decision) {
166-
super(!decision.isGranted());
167-
this.decision = decision;
168+
private NotAuthorizationDecision(AuthorizationResult result) {
169+
super(!result.isGranted());
170+
this.result = result;
168171
}
169172

170173
@Override
171174
public String toString() {
172-
return "NotAuthorizationDecision [decision=" + this.decision + ']';
175+
return "NotAuthorizationDecision [result=" + this.result + ']';
173176
}
174177

175178
}
176179

180+
private interface AuthorizationManagerCheckAdapter<T> extends AuthorizationManager<T> {
181+
182+
@Override
183+
default AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
184+
AuthorizationResult result = authorize(authentication, object);
185+
if (result == null) {
186+
return null;
187+
}
188+
if (result instanceof AuthorizationDecision decision) {
189+
return decision;
190+
}
191+
throw new IllegalArgumentException(
192+
"please call #authorize or ensure that the result is of type AuthorizationDecision");
193+
}
194+
195+
AuthorizationResult authorize(Supplier<Authentication> authentication, T object);
196+
197+
}
198+
177199
}

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

+8-7
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ public class AuthorizationObservationContext<T> extends Observation.Context {
3333

3434
private final T object;
3535

36-
private AuthorizationDecision decision;
37-
3836
private AuthorizationResult authorizationResult;
3937

4038
public AuthorizationObservationContext(T object) {
@@ -77,9 +75,14 @@ public T getObject() {
7775
*/
7876
@Deprecated
7977
public AuthorizationDecision getDecision() {
80-
Assert.isInstanceOf(AuthorizationDecision.class, this.authorizationResult,
78+
if (this.authorizationResult == null) {
79+
return null;
80+
}
81+
if (this.authorizationResult instanceof AuthorizationDecision decision) {
82+
return decision;
83+
}
84+
throw new IllegalArgumentException(
8185
"Please call getAuthorizationResult instead. If you must call getDecision, please ensure that the result you provide is of type AuthorizationDecision");
82-
return (AuthorizationDecision) this.authorizationResult;
8386
}
8487

8588
/**
@@ -89,9 +92,7 @@ public AuthorizationDecision getDecision() {
8992
*/
9093
@Deprecated
9194
public void setDecision(AuthorizationDecision decision) {
92-
Assert.isInstanceOf(AuthorizationDecision.class, decision,
93-
"Please call setAuthorizationResult instead. If you must call getDecision, please ensure that the result you provide is of type AuthorizationDecision");
94-
this.decision = decision;
95+
this.authorizationResult = decision;
9596
}
9697

9798
/**

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

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ public ObservationAuthorizationManager(ObservationRegistry registry, Authorizati
6161
}
6262
}
6363

64+
/**
65+
* @deprecated please use {@link #authorize(Supplier, Object)} instead
66+
*/
67+
@Deprecated
6468
@Override
6569
public AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
6670
AuthorizationObservationContext<T> context = new AuthorizationObservationContext<>(object);

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

+4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public ObservationReactiveAuthorizationManager(ObservationRegistry registry,
5656
}
5757
}
5858

59+
/**
60+
* @deprecated please use {@link #authorize(Mono, Object)} instead
61+
*/
62+
@Deprecated
5963
@Override
6064
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, T object) {
6165
AuthorizationObservationContext<T> context = new AuthorizationObservationContext<>(object);

core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerAfterMethodInterceptor.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -182,22 +182,22 @@ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy strat
182182
private Object attemptAuthorization(MethodInvocation mi, Object result) {
183183
this.logger.debug(LogMessage.of(() -> "Authorizing method invocation " + mi));
184184
MethodInvocationResult object = new MethodInvocationResult(mi, result);
185-
AuthorizationResult decision = this.authorizationManager.authorize(this::getAuthentication, object);
186-
this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, object, decision);
187-
if (decision != null && !decision.isGranted()) {
185+
AuthorizationResult authorizationResult = this.authorizationManager.authorize(this::getAuthentication, object);
186+
this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, object, authorizationResult);
187+
if (authorizationResult != null && !authorizationResult.isGranted()) {
188188
this.logger.debug(LogMessage.of(() -> "Failed to authorize " + mi + " with authorization manager "
189-
+ this.authorizationManager + " and decision " + decision));
190-
return handlePostInvocationDenied(object, decision);
189+
+ this.authorizationManager + " and authorizationResult " + authorizationResult));
190+
return handlePostInvocationDenied(object, authorizationResult);
191191
}
192192
this.logger.debug(LogMessage.of(() -> "Authorized method invocation " + mi));
193193
return result;
194194
}
195195

196-
private Object handlePostInvocationDenied(MethodInvocationResult mi, AuthorizationResult decision) {
196+
private Object handlePostInvocationDenied(MethodInvocationResult mi, AuthorizationResult result) {
197197
if (this.authorizationManager instanceof MethodAuthorizationDeniedHandler deniedHandler) {
198-
return deniedHandler.handleDeniedInvocationResult(mi, decision);
198+
return deniedHandler.handleDeniedInvocationResult(mi, result);
199199
}
200-
return this.defaultHandler.handleDeniedInvocationResult(mi, decision);
200+
return this.defaultHandler.handleDeniedInvocationResult(mi, result);
201201
}
202202

203203
private Authentication getAuthentication() {

core/src/main/java/org/springframework/security/authorization/method/AuthorizationManagerBeforeMethodInterceptor.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -246,18 +246,18 @@ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy secur
246246

247247
private Object attemptAuthorization(MethodInvocation mi) throws Throwable {
248248
this.logger.debug(LogMessage.of(() -> "Authorizing method invocation " + mi));
249-
AuthorizationResult decision;
249+
AuthorizationResult result;
250250
try {
251-
decision = this.authorizationManager.authorize(this::getAuthentication, mi);
251+
result = this.authorizationManager.authorize(this::getAuthentication, mi);
252252
}
253253
catch (AuthorizationDeniedException denied) {
254254
return handle(mi, denied);
255255
}
256-
this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, mi, decision);
257-
if (decision != null && !decision.isGranted()) {
256+
this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, mi, result);
257+
if (result != null && !result.isGranted()) {
258258
this.logger.debug(LogMessage.of(() -> "Failed to authorize " + mi + " with authorization manager "
259-
+ this.authorizationManager + " and decision " + decision));
260-
return handle(mi, decision);
259+
+ this.authorizationManager + " and result " + result));
260+
return handle(mi, result);
261261
}
262262
this.logger.debug(LogMessage.of(() -> "Authorized method invocation " + mi));
263263
return proceed(mi);
@@ -282,11 +282,11 @@ private Object handle(MethodInvocation mi, AuthorizationDeniedException denied)
282282
return this.defaultHandler.handleDeniedInvocation(mi, denied);
283283
}
284284

285-
private Object handle(MethodInvocation mi, AuthorizationResult decision) {
285+
private Object handle(MethodInvocation mi, AuthorizationResult result) {
286286
if (this.authorizationManager instanceof MethodAuthorizationDeniedHandler handler) {
287-
return handler.handleDeniedInvocation(mi, decision);
287+
return handler.handleDeniedInvocation(mi, result);
288288
}
289-
return this.defaultHandler.handleDeniedInvocation(mi, decision);
289+
return this.defaultHandler.handleDeniedInvocation(mi, result);
290290
}
291291

292292
private Authentication getAuthentication() {

0 commit comments

Comments
 (0)