mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-02-08 22:44:35 +00:00
AuthorizationManager allows null Authentication
It is possible to have a null Authentication and so the AuthorizationManager APIs should allow for passing it in. Closes gh-17795
This commit is contained in:
parent
583e668c6b
commit
f496ded4e5
@ -235,13 +235,13 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
||||
* Specify that URLs are allowed by anyone.
|
||||
*/
|
||||
val permitAll: AuthorizationManager<RequestAuthorizationContext> =
|
||||
AuthorizationManager { _: Supplier<Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
|
||||
AuthorizationManager { _: Supplier<Authentication?>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
|
||||
|
||||
/**
|
||||
* Specify that URLs are not allowed by anyone.
|
||||
*/
|
||||
val denyAll: AuthorizationManager<RequestAuthorizationContext> =
|
||||
AuthorizationManager { _: Supplier<Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
|
||||
AuthorizationManager { _: Supplier<Authentication?>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by any authenticated user.
|
||||
|
||||
@ -193,7 +193,7 @@ class AuthorizeHttpRequestsDslTests {
|
||||
open class MvcMatcherPathVariablesConfig {
|
||||
@Bean
|
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
val access = AuthorizationManager { _: Supplier<Authentication>, context: RequestAuthorizationContext ->
|
||||
val access = AuthorizationManager { _: Supplier<Authentication?>, context: RequestAuthorizationContext ->
|
||||
AuthorizationDecision(context.variables["userName"] == "user")
|
||||
}
|
||||
http {
|
||||
|
||||
@ -70,7 +70,7 @@ public abstract class AbstractSecurityExpressionHandler<T>
|
||||
* suitable root object.
|
||||
*/
|
||||
@Override
|
||||
public final EvaluationContext createEvaluationContext(Authentication authentication, T invocation) {
|
||||
public final EvaluationContext createEvaluationContext(@Nullable Authentication authentication, T invocation) {
|
||||
SecurityExpressionOperations root = createSecurityExpressionRoot(authentication, invocation);
|
||||
StandardEvaluationContext ctx = createEvaluationContextInternal(authentication, invocation);
|
||||
if (this.beanResolver != null) {
|
||||
@ -91,7 +91,8 @@ public abstract class AbstractSecurityExpressionHandler<T>
|
||||
* @return A {@code StandardEvaluationContext} or potentially a custom subclass if
|
||||
* overridden.
|
||||
*/
|
||||
protected StandardEvaluationContext createEvaluationContextInternal(Authentication authentication, T invocation) {
|
||||
protected StandardEvaluationContext createEvaluationContextInternal(@Nullable Authentication authentication,
|
||||
T invocation) {
|
||||
return new StandardEvaluationContext();
|
||||
}
|
||||
|
||||
@ -102,8 +103,8 @@ public abstract class AbstractSecurityExpressionHandler<T>
|
||||
* @param invocation the invocation (filter, method, channel)
|
||||
* @return the object
|
||||
*/
|
||||
protected abstract SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
|
||||
T invocation);
|
||||
protected abstract SecurityExpressionOperations createSecurityExpressionRoot(
|
||||
@Nullable Authentication authentication, T invocation);
|
||||
|
||||
protected @Nullable RoleHierarchy getRoleHierarchy() {
|
||||
return this.roleHierarchy;
|
||||
|
||||
@ -18,6 +18,8 @@ package org.springframework.security.access.expression;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
@ -42,7 +44,7 @@ public interface SecurityExpressionHandler<T> extends AopInfrastructureBean {
|
||||
* Provides an evaluation context in which to evaluate security expressions for the
|
||||
* invocation type.
|
||||
*/
|
||||
EvaluationContext createEvaluationContext(Authentication authentication, T invocation);
|
||||
EvaluationContext createEvaluationContext(@Nullable Authentication authentication, T invocation);
|
||||
|
||||
/**
|
||||
* Provides an evaluation context in which to evaluate security expressions for the
|
||||
@ -55,7 +57,7 @@ public interface SecurityExpressionHandler<T> extends AopInfrastructureBean {
|
||||
* @return the {@link EvaluationContext} to use
|
||||
* @since 5.8
|
||||
*/
|
||||
default EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, T invocation) {
|
||||
default EvaluationContext createEvaluationContext(Supplier<@Nullable Authentication> authentication, T invocation) {
|
||||
return createEvaluationContext(authentication.get(), invocation);
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
|
||||
* Creates a new instance
|
||||
* @param authentication the {@link Authentication} to use. Cannot be null.
|
||||
*/
|
||||
public SecurityExpressionRoot(Authentication authentication) {
|
||||
public SecurityExpressionRoot(@Nullable Authentication authentication) {
|
||||
this(() -> authentication);
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
|
||||
* Cannot be null.
|
||||
* @since 5.8
|
||||
*/
|
||||
public SecurityExpressionRoot(Supplier<Authentication> authentication) {
|
||||
public SecurityExpressionRoot(Supplier<@Nullable Authentication> authentication) {
|
||||
this.authentication = SingletonSupplier.of(() -> {
|
||||
Authentication value = authentication.get();
|
||||
Assert.notNull(value, "Authentication object cannot be null");
|
||||
|
||||
@ -79,12 +79,14 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
|
||||
* implementation.
|
||||
*/
|
||||
@Override
|
||||
public StandardEvaluationContext createEvaluationContextInternal(Authentication auth, MethodInvocation mi) {
|
||||
public StandardEvaluationContext createEvaluationContextInternal(@Nullable Authentication auth,
|
||||
MethodInvocation mi) {
|
||||
return new MethodSecurityEvaluationContext(auth, mi, getParameterNameDiscoverer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, MethodInvocation mi) {
|
||||
public EvaluationContext createEvaluationContext(Supplier<@Nullable Authentication> authentication,
|
||||
MethodInvocation mi) {
|
||||
MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);
|
||||
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(root, mi,
|
||||
getParameterNameDiscoverer());
|
||||
@ -96,13 +98,13 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
|
||||
* Creates the root object for expression evaluation.
|
||||
*/
|
||||
@Override
|
||||
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
|
||||
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(@Nullable Authentication authentication,
|
||||
MethodInvocation invocation) {
|
||||
return createSecurityExpressionRoot(() -> authentication, invocation);
|
||||
}
|
||||
|
||||
private MethodSecurityExpressionOperations createSecurityExpressionRoot(Supplier<Authentication> authentication,
|
||||
MethodInvocation invocation) {
|
||||
private MethodSecurityExpressionOperations createSecurityExpressionRoot(
|
||||
Supplier<@Nullable Authentication> authentication, MethodInvocation invocation) {
|
||||
MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
|
||||
root.setThis(invocation.getThis());
|
||||
root.setPermissionEvaluator(getPermissionEvaluator());
|
||||
|
||||
@ -38,11 +38,11 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements Met
|
||||
|
||||
private @Nullable Object target;
|
||||
|
||||
MethodSecurityExpressionRoot(Authentication a) {
|
||||
MethodSecurityExpressionRoot(@Nullable Authentication a) {
|
||||
super(a);
|
||||
}
|
||||
|
||||
MethodSecurityExpressionRoot(Supplier<Authentication> authentication) {
|
||||
MethodSecurityExpressionRoot(Supplier<@Nullable Authentication> authentication) {
|
||||
super(authentication);
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ package org.springframework.security.authorization;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -111,7 +113,7 @@ public final class AuthenticatedAuthorizationManager<T> implements Authorization
|
||||
* @return an {@link AuthorizationDecision}
|
||||
*/
|
||||
@Override
|
||||
public AuthorizationResult authorize(Supplier<Authentication> authentication, T object) {
|
||||
public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object) {
|
||||
boolean granted = this.authorizationStrategy.isGranted(authentication.get());
|
||||
return new AuthorizationDecision(granted);
|
||||
}
|
||||
|
||||
@ -19,6 +19,8 @@ package org.springframework.security.authorization;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -55,7 +57,8 @@ public final class AuthoritiesAuthorizationManager implements AuthorizationManag
|
||||
* @return an {@link AuthorityAuthorizationDecision}
|
||||
*/
|
||||
@Override
|
||||
public AuthorizationResult authorize(Supplier<Authentication> authentication, Collection<String> authorities) {
|
||||
public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
|
||||
Collection<String> authorities) {
|
||||
boolean granted = isGranted(authentication.get(), authorities);
|
||||
return new AuthorityAuthorizationDecision(granted, AuthorityUtils.createAuthorityList(authorities));
|
||||
}
|
||||
|
||||
@ -19,6 +19,8 @@ package org.springframework.security.authorization;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -137,7 +139,7 @@ public final class AuthorityAuthorizationManager<T> implements AuthorizationMana
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public AuthorizationResult authorize(Supplier<Authentication> authentication, T object) {
|
||||
public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object) {
|
||||
return this.delegate.authorize(authentication, this.authorities);
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ public interface AuthorizationManager<T extends @Nullable Object> {
|
||||
* @param object the {@link T} object to check
|
||||
* @throws AccessDeniedException if access is not granted
|
||||
*/
|
||||
default void verify(Supplier<Authentication> authentication, T object) {
|
||||
default void verify(Supplier<@Nullable Authentication> authentication, T object) {
|
||||
AuthorizationResult result = authorize(authentication, object);
|
||||
if (result != null && !result.isGranted()) {
|
||||
throw new AuthorizationDeniedException("Access Denied", result);
|
||||
@ -54,6 +54,6 @@ public interface AuthorizationManager<T extends @Nullable Object> {
|
||||
* @return an {@link AuthorizationResult}
|
||||
* @since 6.4
|
||||
*/
|
||||
@Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, T object);
|
||||
@Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object);
|
||||
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
@ -58,7 +60,7 @@ public final class AuthorizationManagers {
|
||||
@SafeVarargs
|
||||
public static <T> AuthorizationManager<T> anyOf(AuthorizationDecision allAbstainDefaultDecision,
|
||||
AuthorizationManager<T>... managers) {
|
||||
return (AuthorizationManagerCheckAdapter<T>) (authentication, object) -> {
|
||||
return (AuthorizationManagerCheckAdapter<T>) (Supplier<@Nullable Authentication> authentication, T object) -> {
|
||||
List<AuthorizationResult> results = new ArrayList<>();
|
||||
for (AuthorizationManager<T> manager : managers) {
|
||||
AuthorizationResult result = manager.authorize(authentication, object);
|
||||
@ -104,7 +106,7 @@ public final class AuthorizationManagers {
|
||||
@SafeVarargs
|
||||
public static <T> AuthorizationManager<T> allOf(AuthorizationDecision allAbstainDefaultDecision,
|
||||
AuthorizationManager<T>... managers) {
|
||||
return (AuthorizationManagerCheckAdapter<T>) (authentication, object) -> {
|
||||
return (AuthorizationManagerCheckAdapter<T>) (Supplier<@Nullable Authentication> authentication, T object) -> {
|
||||
List<AuthorizationResult> results = new ArrayList<>();
|
||||
for (AuthorizationManager<T> manager : managers) {
|
||||
AuthorizationResult result = manager.authorize(authentication, object);
|
||||
@ -133,7 +135,7 @@ public final class AuthorizationManagers {
|
||||
* @since 6.3
|
||||
*/
|
||||
public static <T> AuthorizationManager<T> not(AuthorizationManager<T> manager) {
|
||||
return (authentication, object) -> {
|
||||
return (Supplier<@Nullable Authentication> authentication, T object) -> {
|
||||
AuthorizationResult result = manager.authorize(authentication, object);
|
||||
if (result == null) {
|
||||
return null;
|
||||
@ -182,7 +184,7 @@ public final class AuthorizationManagers {
|
||||
private interface AuthorizationManagerCheckAdapter<T> extends AuthorizationManager<T> {
|
||||
|
||||
@Override
|
||||
AuthorizationResult authorize(Supplier<Authentication> authentication, T object);
|
||||
AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -63,9 +63,9 @@ public final class ObservationAuthorizationManager<T>
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, T object) {
|
||||
public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object) {
|
||||
AuthorizationObservationContext<T> context = new AuthorizationObservationContext<>(object);
|
||||
Supplier<Authentication> wrapped = () -> {
|
||||
Supplier<@Nullable Authentication> wrapped = () -> {
|
||||
context.setAuthentication(authentication.get());
|
||||
return context.getAuthentication();
|
||||
};
|
||||
|
||||
@ -18,6 +18,8 @@ package org.springframework.security.authorization;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@ -44,7 +46,7 @@ public final class SingleResultAuthorizationManager<C> implements AuthorizationM
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationResult authorize(Supplier<Authentication> authentication, C object) {
|
||||
public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, C object) {
|
||||
if (!(this.result instanceof AuthorizationDecision)) {
|
||||
throw new IllegalArgumentException("result should be AuthorizationDecision");
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ public final class Jsr250AuthorizationManager implements AuthorizationManager<Me
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @Nullable AuthorizationResult authorize(Supplier<Authentication> authentication,
|
||||
public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
|
||||
MethodInvocation methodInvocation) {
|
||||
AuthorizationManager<MethodInvocation> delegate = this.registry.getManager(methodInvocation);
|
||||
return delegate.authorize(authentication, methodInvocation);
|
||||
@ -104,8 +104,9 @@ public final class Jsr250AuthorizationManager implements AuthorizationManager<Me
|
||||
return SingleResultAuthorizationManager.permitAll();
|
||||
}
|
||||
if (annotation instanceof RolesAllowed rolesAllowed) {
|
||||
return (a, o) -> Jsr250AuthorizationManager.this.authoritiesAuthorizationManager.authorize(a,
|
||||
getAllowedRolesWithPrefix(rolesAllowed));
|
||||
return (Supplier<@Nullable Authentication> a,
|
||||
MethodInvocation o) -> Jsr250AuthorizationManager.this.authoritiesAuthorizationManager
|
||||
.authorize(a, getAllowedRolesWithPrefix(rolesAllowed));
|
||||
}
|
||||
return NULL_MANAGER;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ package org.springframework.security.authorization.method;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
@ -73,7 +74,7 @@ public final class MethodExpressionAuthorizationManager implements Authorization
|
||||
* expression
|
||||
*/
|
||||
@Override
|
||||
public AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation context) {
|
||||
public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, MethodInvocation context) {
|
||||
EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context);
|
||||
boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, ctx);
|
||||
return new ExpressionAuthorizationDecision(granted, this.expression);
|
||||
|
||||
@ -86,7 +86,8 @@ public final class PostAuthorizeAuthorizationManager
|
||||
* {@link PostAuthorize} annotation is not present
|
||||
*/
|
||||
@Override
|
||||
public @Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocationResult mi) {
|
||||
public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
|
||||
MethodInvocationResult mi) {
|
||||
ExpressionAttribute attribute = this.registry.getAttribute(mi.getMethodInvocation());
|
||||
if (attribute == null) {
|
||||
return null;
|
||||
|
||||
@ -78,7 +78,8 @@ public final class PreAuthorizeAuthorizationManager
|
||||
* {@link PreAuthorize} annotation is not present
|
||||
*/
|
||||
@Override
|
||||
public @Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation mi) {
|
||||
public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
|
||||
MethodInvocation mi) {
|
||||
ExpressionAttribute attribute = this.registry.getAttribute(mi);
|
||||
if (attribute == null) {
|
||||
return null;
|
||||
|
||||
@ -68,7 +68,8 @@ public final class SecuredAuthorizationManager implements AuthorizationManager<M
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation mi) {
|
||||
public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
|
||||
MethodInvocation mi) {
|
||||
Set<String> authorities = getAuthorities(mi);
|
||||
return authorities.isEmpty() ? null
|
||||
: this.authoritiesAuthorizationManager.authorize(authentication, authorities);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user