1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Enable Null checking in spring-security-web via JSpecify

Closes gh-17535
This commit is contained in:
Rob Winch
2025-08-21 14:02:17 -05:00
parent 49f308adb0
commit c2ba662b91
261 changed files with 1782 additions and 537 deletions
@@ -18,6 +18,8 @@ package org.springframework.security.access;
import java.io.Serializable;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.security.access.intercept.RunAsManager;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
@@ -45,6 +47,7 @@ import org.springframework.security.core.annotation.SecurityAnnotationScanner;
* {@link AuthorizationManager}.
*/
@Deprecated
@NullUnmarked
public interface ConfigAttribute extends Serializable {
/**
@@ -177,7 +177,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
this.trustResolver = trustResolver;
}
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
public void setRoleHierarchy(@Nullable RoleHierarchy roleHierarchy) {
this.roleHierarchy = roleHierarchy;
}
@@ -85,6 +85,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
}
@Override
@SuppressWarnings("NullAway") // FIXME: Dataflow analysis limitation
public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
MethodInvocation mi) {
MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);
@@ -18,6 +18,8 @@ package org.springframework.security.access.vote;
import java.util.Collection;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
@@ -53,6 +55,7 @@ import org.springframework.security.core.GrantedAuthority;
* instead
*/
@Deprecated
@NullUnmarked
public class RoleVoter implements AccessDecisionVoter<Object> {
private String rolePrefix = "ROLE_";
@@ -18,6 +18,7 @@ package org.springframework.security.authentication;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Contract;
import org.springframework.security.core.Authentication;
/**
@@ -80,6 +81,7 @@ public interface AuthenticationTrustResolver {
* {@link Authentication#isAuthenticated()} is true.
* @since 6.1.7
*/
@Contract("null -> false")
default boolean isAuthenticated(@Nullable Authentication authentication) {
return authentication != null && authentication.isAuthenticated() && !isAnonymous(authentication);
}
@@ -39,7 +39,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
private static final long serialVersionUID = 620L;
private final Object principal;
private final @Nullable Object principal;
private @Nullable Object credentials;
@@ -49,7 +49,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
* will return <code>false</code>.
*
*/
public UsernamePasswordAuthenticationToken(Object principal, @Nullable Object credentials) {
public UsernamePasswordAuthenticationToken(@Nullable Object principal, @Nullable Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
@@ -82,7 +82,8 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
*
* @since 5.7
*/
public static UsernamePasswordAuthenticationToken unauthenticated(Object principal, @Nullable Object credentials) {
public static UsernamePasswordAuthenticationToken unauthenticated(@Nullable Object principal,
@Nullable Object credentials) {
return new UsernamePasswordAuthenticationToken(principal, credentials);
}
@@ -106,7 +107,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
}
@Override
public Object getPrincipal() {
public @Nullable Object getPrincipal() {
return this.principal;
}
@@ -178,8 +178,10 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
// applied.
authorities = getAuthorities(principals);
// Convert the authorities set back to an array and apply it to the token.
JaasAuthenticationToken result = new JaasAuthenticationToken(request.getPrincipal(),
request.getCredentials(), new ArrayList<>(authorities), loginContext);
Object principal = request.getPrincipal();
Assert.notNull(principal, "The principal cannot be null");
JaasAuthenticationToken result = new JaasAuthenticationToken(principal, request.getCredentials(),
new ArrayList<>(authorities), loginContext);
// Publish the success event
publishSuccessEvent(result);
// we're done, return the token.
@@ -71,8 +71,8 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
* @deprecated Please use constructor that takes a {@link String} instead
*/
@Deprecated(forRemoval = true, since = "7.0")
public static OneTimeTokenAuthenticationToken unauthenticated(String tokenValue) {
return new OneTimeTokenAuthenticationToken(null, tokenValue);
public static OneTimeTokenAuthenticationToken unauthenticated(@Nullable String tokenValue) {
return new OneTimeTokenAuthenticationToken(null, (tokenValue != null) ? tokenValue : "");
}
/**
@@ -18,6 +18,8 @@ package org.springframework.security.authorization;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
import org.springframework.security.core.Authentication;
@@ -46,6 +48,7 @@ public interface AuthorizationEventPublisher {
* @param <T> the secured object's type
* @since 6.4
*/
<T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object, AuthorizationResult result);
<T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
@Nullable AuthorizationResult result);
}
@@ -19,6 +19,8 @@ package org.springframework.security.authorization;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
@@ -57,7 +59,7 @@ public final class SpringAuthorizationEventPublisher implements AuthorizationEve
*/
@Override
public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
AuthorizationResult result) {
@Nullable AuthorizationResult result) {
if (result == null) {
return;
}
@@ -74,6 +74,7 @@ public final class MethodExpressionAuthorizationManager implements Authorization
* expression
*/
@Override
@SuppressWarnings("NullAway") // FIXME: Dataflow analysis limitation
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
MethodInvocation context) {
EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context);
@@ -18,6 +18,8 @@ package org.springframework.security.authorization.method;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authorization.AuthorizationEventPublisher;
import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.core.Authentication;
@@ -32,7 +34,7 @@ final class NoOpAuthorizationEventPublisher implements AuthorizationEventPublish
@Override
public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
AuthorizationResult result) {
@Nullable AuthorizationResult result) {
}
@@ -76,7 +76,7 @@ public abstract class AuthenticationException extends RuntimeException {
* authentication attempt
* @since 6.5
*/
public void setAuthenticationRequest(Authentication authenticationRequest) {
public void setAuthenticationRequest(@Nullable Authentication authenticationRequest) {
Assert.notNull(authenticationRequest, "authenticationRequest cannot be null");
this.authenticationRequest = authenticationRequest;
}