Skip to content

Commit 2fbbcc4

Browse files
Polish Method Authorization Denied Handling
- Renamed @AuthorizationDeniedHandler to @HandleAuthorizationDenied - Merged the post processor interface into MethodAuthorizationDeniedHandler , it now has two methods handleDeniedInvocation and handleDeniedInvocationResult - @HandleAuthorizationDenied now handles AuthorizationDeniedException thrown from the method Issue gh-14601
1 parent 14da8f4 commit 2fbbcc4

File tree

31 files changed

+425
-440
lines changed

31 files changed

+425
-440
lines changed

config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationAuthorizationManager.java

+5-12
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,18 @@
2727
import org.springframework.security.authorization.AuthorizationResult;
2828
import org.springframework.security.authorization.ObservationAuthorizationManager;
2929
import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
30-
import org.springframework.security.authorization.method.MethodAuthorizationDeniedPostProcessor;
3130
import org.springframework.security.authorization.method.MethodInvocationResult;
3231
import org.springframework.security.authorization.method.ThrowingMethodAuthorizationDeniedHandler;
33-
import org.springframework.security.authorization.method.ThrowingMethodAuthorizationDeniedPostProcessor;
3432
import org.springframework.security.core.Authentication;
3533
import org.springframework.util.function.SingletonSupplier;
3634

3735
final class DeferringObservationAuthorizationManager<T>
38-
implements AuthorizationManager<T>, MethodAuthorizationDeniedHandler, MethodAuthorizationDeniedPostProcessor {
36+
implements AuthorizationManager<T>, MethodAuthorizationDeniedHandler {
3937

4038
private final Supplier<AuthorizationManager<T>> delegate;
4139

4240
private MethodAuthorizationDeniedHandler handler = new ThrowingMethodAuthorizationDeniedHandler();
4341

44-
private MethodAuthorizationDeniedPostProcessor postProcessor = new ThrowingMethodAuthorizationDeniedPostProcessor();
45-
4642
DeferringObservationAuthorizationManager(ObjectProvider<ObservationRegistry> provider,
4743
AuthorizationManager<T> delegate) {
4844
this.delegate = SingletonSupplier.of(() -> {
@@ -55,9 +51,6 @@ final class DeferringObservationAuthorizationManager<T>
5551
if (delegate instanceof MethodAuthorizationDeniedHandler h) {
5652
this.handler = h;
5753
}
58-
if (delegate instanceof MethodAuthorizationDeniedPostProcessor p) {
59-
this.postProcessor = p;
60-
}
6154
}
6255

6356
@Override
@@ -66,14 +59,14 @@ public AuthorizationDecision check(Supplier<Authentication> authentication, T ob
6659
}
6760

6861
@Override
69-
public Object handle(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
70-
return this.handler.handle(methodInvocation, authorizationResult);
62+
public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
63+
return this.handler.handleDeniedInvocation(methodInvocation, authorizationResult);
7164
}
7265

7366
@Override
74-
public Object postProcessResult(MethodInvocationResult methodInvocationResult,
67+
public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
7568
AuthorizationResult authorizationResult) {
76-
return this.postProcessor.postProcessResult(methodInvocationResult, authorizationResult);
69+
return this.handler.handleDeniedInvocationResult(methodInvocationResult, authorizationResult);
7770
}
7871

7972
}

config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationReactiveAuthorizationManager.java

+6-13
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,18 @@
2828
import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
2929
import org.springframework.security.authorization.ReactiveAuthorizationManager;
3030
import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
31-
import org.springframework.security.authorization.method.MethodAuthorizationDeniedPostProcessor;
3231
import org.springframework.security.authorization.method.MethodInvocationResult;
3332
import org.springframework.security.authorization.method.ThrowingMethodAuthorizationDeniedHandler;
34-
import org.springframework.security.authorization.method.ThrowingMethodAuthorizationDeniedPostProcessor;
3533
import org.springframework.security.core.Authentication;
3634
import org.springframework.util.function.SingletonSupplier;
3735

38-
final class DeferringObservationReactiveAuthorizationManager<T> implements ReactiveAuthorizationManager<T>,
39-
MethodAuthorizationDeniedHandler, MethodAuthorizationDeniedPostProcessor {
36+
final class DeferringObservationReactiveAuthorizationManager<T>
37+
implements ReactiveAuthorizationManager<T>, MethodAuthorizationDeniedHandler {
4038

4139
private final Supplier<ReactiveAuthorizationManager<T>> delegate;
4240

4341
private MethodAuthorizationDeniedHandler handler = new ThrowingMethodAuthorizationDeniedHandler();
4442

45-
private MethodAuthorizationDeniedPostProcessor postProcessor = new ThrowingMethodAuthorizationDeniedPostProcessor();
46-
4743
DeferringObservationReactiveAuthorizationManager(ObjectProvider<ObservationRegistry> provider,
4844
ReactiveAuthorizationManager<T> delegate) {
4945
this.delegate = SingletonSupplier.of(() -> {
@@ -56,9 +52,6 @@ final class DeferringObservationReactiveAuthorizationManager<T> implements React
5652
if (delegate instanceof MethodAuthorizationDeniedHandler h) {
5753
this.handler = h;
5854
}
59-
if (delegate instanceof MethodAuthorizationDeniedPostProcessor p) {
60-
this.postProcessor = p;
61-
}
6255
}
6356

6457
@Override
@@ -67,14 +60,14 @@ public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, T
6760
}
6861

6962
@Override
70-
public Object handle(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
71-
return this.handler.handle(methodInvocation, authorizationResult);
63+
public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
64+
return this.handler.handleDeniedInvocation(methodInvocation, authorizationResult);
7265
}
7366

7467
@Override
75-
public Object postProcessResult(MethodInvocationResult methodInvocationResult,
68+
public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
7669
AuthorizationResult authorizationResult) {
77-
return this.postProcessor.postProcessResult(methodInvocationResult, authorizationResult);
70+
return this.handler.handleDeniedInvocationResult(methodInvocationResult, authorizationResult);
7871
}
7972

8073
}

config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java

+50-30
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,9 @@
3939
import org.springframework.security.access.prepost.PreAuthorize;
4040
import org.springframework.security.access.prepost.PreFilter;
4141
import org.springframework.security.authorization.AuthorizationResult;
42-
import org.springframework.security.authorization.method.AuthorizationDeniedHandler;
4342
import org.springframework.security.authorization.method.AuthorizeReturnObject;
43+
import org.springframework.security.authorization.method.HandleAuthorizationDenied;
4444
import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
45-
import org.springframework.security.authorization.method.MethodAuthorizationDeniedPostProcessor;
4645
import org.springframework.security.authorization.method.MethodInvocationResult;
4746
import org.springframework.security.core.Authentication;
4847
import org.springframework.security.core.context.SecurityContextHolder;
@@ -129,73 +128,72 @@ public interface MethodSecurityService {
129128
void repeatedAnnotations();
130129

131130
@PreAuthorize("hasRole('ADMIN')")
132-
@AuthorizationDeniedHandler(handlerClass = StarMaskingHandler.class)
131+
@HandleAuthorizationDenied(handlerClass = StarMaskingHandler.class)
133132
String preAuthorizeGetCardNumberIfAdmin(String cardNumber);
134133

135134
@PreAuthorize("hasRole('ADMIN')")
136-
@AuthorizationDeniedHandler(handlerClass = StartMaskingHandlerChild.class)
135+
@HandleAuthorizationDenied(handlerClass = StartMaskingHandlerChild.class)
137136
String preAuthorizeWithHandlerChildGetCardNumberIfAdmin(String cardNumber);
138137

139138
@PreAuthorize("hasRole('ADMIN')")
140-
@AuthorizationDeniedHandler(handlerClass = StarMaskingHandler.class)
139+
@HandleAuthorizationDenied(handlerClass = StarMaskingHandler.class)
141140
String preAuthorizeThrowAccessDeniedManually();
142141

143142
@PostAuthorize("hasRole('ADMIN')")
144-
@AuthorizationDeniedHandler(postProcessorClass = CardNumberMaskingPostProcessor.class)
143+
@HandleAuthorizationDenied(handlerClass = CardNumberMaskingPostProcessor.class)
145144
String postAuthorizeGetCardNumberIfAdmin(String cardNumber);
146145

147146
@PostAuthorize("hasRole('ADMIN')")
148-
@AuthorizationDeniedHandler(postProcessorClass = PostMaskingPostProcessor.class)
147+
@HandleAuthorizationDenied(handlerClass = PostMaskingPostProcessor.class)
149148
String postAuthorizeThrowAccessDeniedManually();
150149

151150
@PreAuthorize("denyAll()")
152151
@Mask("methodmask")
153-
@AuthorizationDeniedHandler(handlerClass = MaskAnnotationHandler.class)
152+
@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
154153
String preAuthorizeDeniedMethodWithMaskAnnotation();
155154

156155
@PreAuthorize("denyAll()")
157-
@AuthorizationDeniedHandler(handlerClass = MaskAnnotationHandler.class)
156+
@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
158157
String preAuthorizeDeniedMethodWithNoMaskAnnotation();
159158

160159
@NullDenied(role = "ADMIN")
161160
String postAuthorizeDeniedWithNullDenied();
162161

163162
@PostAuthorize("denyAll()")
164163
@Mask("methodmask")
165-
@AuthorizationDeniedHandler(postProcessorClass = MaskAnnotationPostProcessor.class)
164+
@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
166165
String postAuthorizeDeniedMethodWithMaskAnnotation();
167166

168167
@PostAuthorize("denyAll()")
169-
@AuthorizationDeniedHandler(postProcessorClass = MaskAnnotationPostProcessor.class)
168+
@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
170169
String postAuthorizeDeniedMethodWithNoMaskAnnotation();
171170

172171
@PreAuthorize("hasRole('ADMIN')")
173172
@Mask(expression = "@myMasker.getMask()")
174-
@AuthorizationDeniedHandler(handlerClass = MaskAnnotationHandler.class)
173+
@HandleAuthorizationDenied(handlerClass = MaskAnnotationHandler.class)
175174
String preAuthorizeWithMaskAnnotationUsingBean();
176175

177176
@PostAuthorize("hasRole('ADMIN')")
178177
@Mask(expression = "@myMasker.getMask(returnObject)")
179-
@AuthorizationDeniedHandler(postProcessorClass = MaskAnnotationPostProcessor.class)
178+
@HandleAuthorizationDenied(handlerClass = MaskAnnotationPostProcessor.class)
180179
String postAuthorizeWithMaskAnnotationUsingBean();
181180

182181
@AuthorizeReturnObject
183182
UserRecordWithEmailProtected getUserRecordWithEmailProtected();
184183

185184
@PreAuthorize("hasRole('ADMIN')")
186-
@AuthorizationDeniedHandler(handlerClass = UserFallbackDeniedHandler.class)
185+
@HandleAuthorizationDenied(handlerClass = UserFallbackDeniedHandler.class)
187186
UserRecordWithEmailProtected getUserWithFallbackWhenUnauthorized();
188187

189188
@PreAuthorize("@authz.checkResult(#result)")
190189
@PostAuthorize("@authz.checkResult(!#result)")
191-
@AuthorizationDeniedHandler(handlerClass = MethodAuthorizationDeniedHandler.class,
192-
postProcessorClass = MethodAuthorizationDeniedPostProcessor.class)
190+
@HandleAuthorizationDenied(handlerClass = MethodAuthorizationDeniedHandler.class)
193191
String checkCustomResult(boolean result);
194192

195193
class StarMaskingHandler implements MethodAuthorizationDeniedHandler {
196194

197195
@Override
198-
public Object handle(MethodInvocation methodInvocation, AuthorizationResult result) {
196+
public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult result) {
199197
return "***";
200198
}
201199

@@ -204,8 +202,8 @@ public Object handle(MethodInvocation methodInvocation, AuthorizationResult resu
204202
class StartMaskingHandlerChild extends StarMaskingHandler {
205203

206204
@Override
207-
public Object handle(MethodInvocation methodInvocation, AuthorizationResult result) {
208-
return super.handle(methodInvocation, result) + "-child";
205+
public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult result) {
206+
return super.handleDeniedInvocation(methodInvocation, result) + "-child";
209207
}
210208

211209
}
@@ -218,7 +216,6 @@ class MaskAnnotationHandler implements MethodAuthorizationDeniedHandler {
218216
this.maskValueResolver = new MaskValueResolver(context);
219217
}
220218

221-
@Override
222219
public Object handle(MethodInvocation methodInvocation, AuthorizationResult result) {
223220
Mask mask = AnnotationUtils.getAnnotation(methodInvocation.getMethod(), Mask.class);
224221
if (mask == null) {
@@ -227,9 +224,15 @@ public Object handle(MethodInvocation methodInvocation, AuthorizationResult resu
227224
return this.maskValueResolver.resolveValue(mask, methodInvocation, null);
228225
}
229226

227+
@Override
228+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
229+
AuthorizationResult authorizationResult) {
230+
return handle(methodInvocation, authorizationResult);
231+
}
232+
230233
}
231234

232-
class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedPostProcessor {
235+
class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedHandler {
233236

234237
MaskValueResolver maskValueResolver;
235238

@@ -238,7 +241,16 @@ class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedPostProces
238241
}
239242

240243
@Override
241-
public Object postProcessResult(MethodInvocationResult methodInvocationResult,
244+
public Object handleDeniedInvocation(MethodInvocation mi, AuthorizationResult authorizationResult) {
245+
Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
246+
if (mask == null) {
247+
mask = AnnotationUtils.getAnnotation(mi.getMethod().getDeclaringClass(), Mask.class);
248+
}
249+
return this.maskValueResolver.resolveValue(mask, mi, null);
250+
}
251+
252+
@Override
253+
public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
242254
AuthorizationResult authorizationResult) {
243255
MethodInvocation mi = methodInvocationResult.getMethodInvocation();
244256
Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
@@ -274,31 +286,38 @@ String resolveValue(Mask mask, MethodInvocation mi, Object returnObject) {
274286

275287
}
276288

277-
class PostMaskingPostProcessor implements MethodAuthorizationDeniedPostProcessor {
289+
class PostMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
278290

279291
@Override
280-
public Object postProcessResult(MethodInvocationResult contextObject, AuthorizationResult result) {
292+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
293+
AuthorizationResult authorizationResult) {
281294
return "***";
282295
}
283296

284297
}
285298

286-
class CardNumberMaskingPostProcessor implements MethodAuthorizationDeniedPostProcessor {
299+
class CardNumberMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
287300

288301
static String MASK = "****-****-****-";
289302

290303
@Override
291-
public Object postProcessResult(MethodInvocationResult contextObject, AuthorizationResult result) {
304+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
305+
AuthorizationResult authorizationResult) {
306+
return "***";
307+
}
308+
309+
@Override
310+
public Object handleDeniedInvocationResult(MethodInvocationResult contextObject, AuthorizationResult result) {
292311
String cardNumber = (String) contextObject.getResult();
293312
return MASK + cardNumber.substring(cardNumber.length() - 4);
294313
}
295314

296315
}
297316

298-
class NullPostProcessor implements MethodAuthorizationDeniedPostProcessor {
317+
class NullPostProcessor implements MethodAuthorizationDeniedHandler {
299318

300319
@Override
301-
public Object postProcessResult(MethodInvocationResult methodInvocationResult,
320+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
302321
AuthorizationResult authorizationResult) {
303322
return null;
304323
}
@@ -320,7 +339,7 @@ public Object postProcessResult(MethodInvocationResult methodInvocationResult,
320339
@Retention(RetentionPolicy.RUNTIME)
321340
@Inherited
322341
@PostAuthorize("hasRole('{role}')")
323-
@AuthorizationDeniedHandler(postProcessorClass = NullPostProcessor.class)
342+
@HandleAuthorizationDenied(handlerClass = NullPostProcessor.class)
324343
@interface NullDenied {
325344

326345
String role();
@@ -333,7 +352,8 @@ class UserFallbackDeniedHandler implements MethodAuthorizationDeniedHandler {
333352
"Protected");
334353

335354
@Override
336-
public Object handle(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
355+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
356+
AuthorizationResult authorizationResult) {
337357
return FALLBACK;
338358
}
339359

config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
import java.util.List;
2020

21-
import org.springframework.security.access.AccessDeniedException;
21+
import org.springframework.security.authorization.AuthorizationDecision;
22+
import org.springframework.security.authorization.AuthorizationDeniedException;
2223
import org.springframework.security.core.Authentication;
2324
import org.springframework.security.core.context.SecurityContextHolder;
2425

@@ -144,12 +145,12 @@ public String preAuthorizeWithHandlerChildGetCardNumberIfAdmin(String cardNumber
144145

145146
@Override
146147
public String preAuthorizeThrowAccessDeniedManually() {
147-
throw new AccessDeniedException("Access Denied");
148+
throw new AuthorizationDeniedException("Access Denied", new AuthorizationDecision(false));
148149
}
149150

150151
@Override
151152
public String postAuthorizeThrowAccessDeniedManually() {
152-
throw new AccessDeniedException("Access Denied");
153+
throw new AuthorizationDeniedException("Access Denied", new AuthorizationDecision(false));
153154
}
154155

155156
@Override

0 commit comments

Comments
 (0)