Polish AuthorizationDeniedException Handling

Issue gh-14600
This commit is contained in:
Josh Cummings 2024-04-11 13:49:14 -06:00
parent b1b84f9b8a
commit 933ef67637
No known key found for this signature in database
GPG Key ID: A306A51F43B8E5A5
9 changed files with 18 additions and 91 deletions

View File

@ -25,7 +25,7 @@ import org.springframework.util.Assert;
* @author Marcus da Coregio
* @since 6.3
*/
public class AuthorizationDeniedException extends AccessDeniedException {
public class AuthorizationDeniedException extends AccessDeniedException implements AuthorizationResult {
private final AuthorizationResult result;
@ -40,4 +40,9 @@ public class AuthorizationDeniedException extends AccessDeniedException {
return this.result;
}
@Override
public boolean isGranted() {
return false;
}
}

View File

@ -33,6 +33,7 @@ import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.authorization.AuthorizationEventPublisher;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
@ -190,14 +191,7 @@ public final class AuthorizationManagerAfterMethodInterceptor implements Authori
return result;
}
private Object postProcess(MethodInvocationResult mi, AuthorizationDeniedException denied) {
if (this.authorizationManager instanceof MethodAuthorizationDeniedPostProcessor postProcessableDecision) {
return postProcessableDecision.postProcessResult(mi, denied);
}
return this.defaultPostProcessor.postProcessResult(mi, denied);
}
private Object postProcess(MethodInvocationResult mi, AuthorizationDecision decision) {
private Object postProcess(MethodInvocationResult mi, AuthorizationResult decision) {
if (this.authorizationManager instanceof MethodAuthorizationDeniedPostProcessor postProcessableDecision) {
return postProcessableDecision.postProcessResult(mi, decision);
}

View File

@ -35,6 +35,7 @@ import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
@ -165,22 +166,7 @@ public final class AuthorizationManagerAfterReactiveMethodInterceptor implements
});
}
private Mono<Object> postProcess(AuthorizationDeniedException denied,
MethodInvocationResult methodInvocationResult) {
return Mono.fromSupplier(() -> {
if (this.authorizationManager instanceof MethodAuthorizationDeniedPostProcessor postProcessableDecision) {
return postProcessableDecision.postProcessResult(methodInvocationResult, denied);
}
return this.defaultPostProcessor.postProcessResult(methodInvocationResult, denied);
}).flatMap((processedResult) -> {
if (Mono.class.isAssignableFrom(processedResult.getClass())) {
return (Mono<?>) processedResult;
}
return Mono.justOrEmpty(processedResult);
});
}
private Mono<Object> postProcess(AuthorizationDecision decision, MethodInvocationResult methodInvocationResult) {
private Mono<Object> postProcess(AuthorizationResult decision, MethodInvocationResult methodInvocationResult) {
if (decision.isGranted()) {
return Mono.just(methodInvocationResult.getResult());
}

View File

@ -264,13 +264,6 @@ public final class AuthorizationManagerBeforeMethodInterceptor implements Author
return mi.proceed();
}
private Object handle(MethodInvocation mi, AuthorizationDeniedException denied) {
if (this.authorizationManager instanceof MethodAuthorizationDeniedHandler handler) {
return handler.handle(mi, denied);
}
return this.defaultHandler.handle(mi, denied);
}
private Object handle(MethodInvocation mi, AuthorizationResult decision) {
if (this.authorizationManager instanceof MethodAuthorizationDeniedHandler handler) {
return handler.handle(mi, decision);

View File

@ -34,6 +34,7 @@ import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
@ -177,21 +178,7 @@ public final class AuthorizationManagerBeforeReactiveMethodInterceptor implement
});
}
private Mono<Object> postProcess(AuthorizationDeniedException denied, MethodInvocation mi) {
return Mono.fromSupplier(() -> {
if (this.authorizationManager instanceof MethodAuthorizationDeniedHandler handler) {
return handler.handle(mi, denied);
}
return this.defaultHandler.handle(mi, denied);
}).flatMap((processedResult) -> {
if (Mono.class.isAssignableFrom(processedResult.getClass())) {
return (Mono<?>) processedResult;
}
return Mono.justOrEmpty(processedResult);
});
}
private Mono<Object> postProcess(AuthorizationDecision decision, MethodInvocation mi) {
private Mono<Object> postProcess(AuthorizationResult decision, MethodInvocation mi) {
return Mono.fromSupplier(() -> {
if (this.authorizationManager instanceof MethodAuthorizationDeniedHandler handler) {
return handler.handle(mi, decision);

View File

@ -19,7 +19,6 @@ package org.springframework.security.authorization.method;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.authorization.AuthorizationResult;
/**
@ -44,18 +43,4 @@ public interface MethodAuthorizationDeniedHandler {
@Nullable
Object handle(MethodInvocation methodInvocation, AuthorizationResult authorizationResult);
/**
* Handle denied method invocations, implementations might either throw an
* {@link org.springframework.security.access.AccessDeniedException} or a replacement
* result instead of invoking the method, e.g. a masked value.
* @param methodInvocation the {@link MethodInvocation} related to the authorization
* denied
* @param authorizationDenied the authorization denied exception
* @return a replacement result for the denied method invocation, or null, or a
* {@link reactor.core.publisher.Mono} for reactive applications
*/
default Object handle(MethodInvocation methodInvocation, AuthorizationDeniedException authorizationDenied) {
return handle(methodInvocation, authorizationDenied.getAuthorizationResult());
}
}

View File

@ -17,7 +17,6 @@
package org.springframework.security.authorization.method;
import org.springframework.lang.Nullable;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.authorization.AuthorizationResult;
/**
@ -44,21 +43,4 @@ public interface MethodAuthorizationDeniedPostProcessor {
@Nullable
Object postProcessResult(MethodInvocationResult methodInvocationResult, AuthorizationResult authorizationResult);
/**
* Post-process the denied result produced by a method invocation, implementations
* might either throw an
* {@link org.springframework.security.access.AccessDeniedException} or return a
* replacement result instead of the denied result, e.g. a masked value.
* @param methodInvocationResult the object containing the method invocation and the
* result produced
* @param authorizationDenied the {@link AuthorizationDeniedException} containing the
* authorization denied details
* @return a replacement result for the denied result, or null, or a
* {@link reactor.core.publisher.Mono} for reactive applications
*/
default Object postProcessResult(MethodInvocationResult methodInvocationResult,
AuthorizationDeniedException authorizationDenied) {
return postProcessResult(methodInvocationResult, authorizationDenied.getAuthorizationResult());
}
}

View File

@ -32,12 +32,10 @@ public final class ThrowingMethodAuthorizationDeniedHandler implements MethodAut
@Override
public Object handle(MethodInvocation methodInvocation, AuthorizationResult result) {
if (result instanceof AuthorizationDeniedException denied) {
throw denied;
}
throw new AuthorizationDeniedException("Access Denied", result);
}
@Override
public Object handle(MethodInvocation methodInvocation, AuthorizationDeniedException authorizationDenied) {
throw authorizationDenied;
}
}

View File

@ -30,13 +30,10 @@ public final class ThrowingMethodAuthorizationDeniedPostProcessor implements Met
@Override
public Object postProcessResult(MethodInvocationResult methodInvocationResult, AuthorizationResult result) {
if (result instanceof AuthorizationDeniedException denied) {
throw denied;
}
throw new AuthorizationDeniedException("Access Denied", result);
}
@Override
public Object postProcessResult(MethodInvocationResult methodInvocationResult,
AuthorizationDeniedException authorizationDenied) {
throw authorizationDenied;
}
}