Skip to content

Commit 5e4935d

Browse files
Polish Method Authorization Denied Handling
Issue spring-projectsgh-14601
1 parent 0c56c54 commit 5e4935d

File tree

31 files changed

+436
-445
lines changed

31 files changed

+436
-445
lines changed

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

Lines changed: 5 additions & 12 deletions
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

Lines changed: 6 additions & 13 deletions
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

Lines changed: 67 additions & 30 deletions
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;
42+
import org.springframework.security.authorization.method.HandleAuthorizationDenied;
4343
import org.springframework.security.authorization.method.AuthorizeReturnObject;
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,21 @@ 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+
233+
@Override
234+
public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
235+
AuthorizationResult authorizationResult) {
236+
return handle(methodInvocationResult.getMethodInvocation(), authorizationResult);
237+
}
238+
230239
}
231240

232-
class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedPostProcessor {
241+
class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedHandler {
233242

234243
MaskValueResolver maskValueResolver;
235244

@@ -238,7 +247,16 @@ class MaskAnnotationPostProcessor implements MethodAuthorizationDeniedPostProces
238247
}
239248

240249
@Override
241-
public Object postProcessResult(MethodInvocationResult methodInvocationResult,
250+
public Object handleDeniedInvocation(MethodInvocation mi, AuthorizationResult authorizationResult) {
251+
Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
252+
if (mask == null) {
253+
mask = AnnotationUtils.getAnnotation(mi.getMethod().getDeclaringClass(), Mask.class);
254+
}
255+
return this.maskValueResolver.resolveValue(mask, mi, null);
256+
}
257+
258+
@Override
259+
public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
242260
AuthorizationResult authorizationResult) {
243261
MethodInvocation mi = methodInvocationResult.getMethodInvocation();
244262
Mask mask = AnnotationUtils.getAnnotation(mi.getMethod(), Mask.class);
@@ -274,31 +292,49 @@ String resolveValue(Mask mask, MethodInvocation mi, Object returnObject) {
274292

275293
}
276294

277-
class PostMaskingPostProcessor implements MethodAuthorizationDeniedPostProcessor {
295+
class PostMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
278296

279297
@Override
280-
public Object postProcessResult(MethodInvocationResult contextObject, AuthorizationResult result) {
298+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
299+
AuthorizationResult authorizationResult) {
300+
return "***";
301+
}
302+
303+
@Override
304+
public Object handleDeniedInvocationResult(MethodInvocationResult contextObject, AuthorizationResult result) {
281305
return "***";
282306
}
283307

284308
}
285309

286-
class CardNumberMaskingPostProcessor implements MethodAuthorizationDeniedPostProcessor {
310+
class CardNumberMaskingPostProcessor implements MethodAuthorizationDeniedHandler {
287311

288312
static String MASK = "****-****-****-";
289313

290314
@Override
291-
public Object postProcessResult(MethodInvocationResult contextObject, AuthorizationResult result) {
315+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
316+
AuthorizationResult authorizationResult) {
317+
return "***";
318+
}
319+
320+
@Override
321+
public Object handleDeniedInvocationResult(MethodInvocationResult contextObject, AuthorizationResult result) {
292322
String cardNumber = (String) contextObject.getResult();
293323
return MASK + cardNumber.substring(cardNumber.length() - 4);
294324
}
295325

296326
}
297327

298-
class NullPostProcessor implements MethodAuthorizationDeniedPostProcessor {
328+
class NullPostProcessor implements MethodAuthorizationDeniedHandler {
329+
330+
@Override
331+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
332+
AuthorizationResult authorizationResult) {
333+
return null;
334+
}
299335

300336
@Override
301-
public Object postProcessResult(MethodInvocationResult methodInvocationResult,
337+
public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
302338
AuthorizationResult authorizationResult) {
303339
return null;
304340
}
@@ -320,7 +356,7 @@ public Object postProcessResult(MethodInvocationResult methodInvocationResult,
320356
@Retention(RetentionPolicy.RUNTIME)
321357
@Inherited
322358
@PostAuthorize("hasRole('{role}')")
323-
@AuthorizationDeniedHandler(postProcessorClass = NullPostProcessor.class)
359+
@HandleAuthorizationDenied(handlerClass = NullPostProcessor.class)
324360
@interface NullDenied {
325361

326362
String role();
@@ -333,7 +369,8 @@ class UserFallbackDeniedHandler implements MethodAuthorizationDeniedHandler {
333369
"Protected");
334370

335371
@Override
336-
public Object handle(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
372+
public Object handleDeniedInvocation(MethodInvocation methodInvocation,
373+
AuthorizationResult authorizationResult) {
337374
return FALLBACK;
338375
}
339376

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

Lines changed: 4 additions & 3 deletions
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)