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
No known key found for this signature in database
261 changed files with 1782 additions and 537 deletions

View File

@ -367,7 +367,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterConfig::class.java).autowire() this.spring.register(CustomFilterConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Filter> = filterChain.getFilters("/") val filters: List<Filter>? = filterChain.getFilters("/")
assertThat(filters).anyMatch { it is CustomFilter } assertThat(filters).anyMatch { it is CustomFilter }
} }
@ -390,7 +390,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterConfigReified::class.java).autowire() this.spring.register(CustomFilterConfigReified::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Filter> = filterChain.getFilters("/") val filters: List<Filter>? = filterChain.getFilters("/")
assertThat(filters).anyMatch { it is CustomFilter } assertThat(filters).anyMatch { it is CustomFilter }
} }
@ -413,7 +413,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterAfterConfig::class.java).autowire() this.spring.register(CustomFilterAfterConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass } val filters: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
assertThat(filters).containsSubsequence( assertThat(filters).containsSubsequence(
UsernamePasswordAuthenticationFilter::class.java, UsernamePasswordAuthenticationFilter::class.java,
@ -440,7 +440,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterAfterConfigReified::class.java).autowire() this.spring.register(CustomFilterAfterConfigReified::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass } val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
assertThat(filterClasses).containsSubsequence( assertThat(filterClasses).containsSubsequence(
UsernamePasswordAuthenticationFilter::class.java, UsernamePasswordAuthenticationFilter::class.java,
@ -467,7 +467,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterBeforeConfig::class.java).autowire() this.spring.register(CustomFilterBeforeConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filters: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass } val filters: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
assertThat(filters).containsSubsequence( assertThat(filters).containsSubsequence(
CustomFilter::class.java, CustomFilter::class.java,
@ -494,7 +494,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomFilterBeforeConfigReified::class.java).autowire() this.spring.register(CustomFilterBeforeConfigReified::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass } val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
assertThat(filterClasses).containsSubsequence( assertThat(filterClasses).containsSubsequence(
CustomFilter::class.java, CustomFilter::class.java,
@ -523,7 +523,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomSecurityConfigurerConfig::class.java).autowire() this.spring.register(CustomSecurityConfigurerConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass } val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
assertThat(filterClasses).contains( assertThat(filterClasses).contains(
CustomFilter::class.java CustomFilter::class.java
@ -535,7 +535,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomSecurityConfigurerConfig::class.java).autowire() this.spring.register(CustomSecurityConfigurerConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass } val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
assertThat(filterClasses).contains( assertThat(filterClasses).contains(
CustomFilter::class.java CustomFilter::class.java
@ -588,7 +588,7 @@ class HttpSecurityDslTests {
this.spring.register(CustomDslUsingWithConfig::class.java).autowire() this.spring.register(CustomDslUsingWithConfig::class.java).autowire()
val filterChain = spring.context.getBean(FilterChainProxy::class.java) val filterChain = spring.context.getBean(FilterChainProxy::class.java)
val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/").map { it.javaClass } val filterClasses: List<Class<out Filter>> = filterChain.getFilters("/")!!.map { it.javaClass }
assertThat(filterClasses).contains( assertThat(filterClasses).contains(
UsernamePasswordAuthenticationFilter::class.java UsernamePasswordAuthenticationFilter::class.java

View File

@ -350,8 +350,8 @@ class LogoutDslTests {
class NoopLogoutHandler: LogoutHandler { class NoopLogoutHandler: LogoutHandler {
override fun logout( override fun logout(
request: HttpServletRequest?, request: HttpServletRequest,
response: HttpServletResponse?, response: HttpServletResponse,
authentication: Authentication? authentication: Authentication?
) { } ) { }

View File

@ -132,8 +132,8 @@ class RequiresChannelDslTests {
companion object { companion object {
val CHANNEL_PROCESSOR: ChannelProcessor = object : ChannelProcessor { val CHANNEL_PROCESSOR: ChannelProcessor = object : ChannelProcessor {
override fun decide(invocation: FilterInvocation?, config: MutableCollection<ConfigAttribute>?) {} override fun decide(invocation: FilterInvocation, config: MutableCollection<ConfigAttribute>) {}
override fun supports(attribute: ConfigAttribute?): Boolean = true override fun supports(attribute: ConfigAttribute): Boolean = true
} }
} }

View File

@ -93,7 +93,7 @@ class SecurityContextDslTests {
testContext.autowire() testContext.autowire()
val filterChainProxy = testContext.context.getBean(FilterChainProxy::class.java) val filterChainProxy = testContext.context.getBean(FilterChainProxy::class.java)
// @formatter:off // @formatter:off
val filterTypes = filterChainProxy.getFilters("/").toList() val filterTypes = filterChainProxy.getFilters("/")!!.toList()
assertThat(filterTypes) assertThat(filterTypes)
.anyMatch { it is SecurityContextHolderFilter } .anyMatch { it is SecurityContextHolderFilter }

View File

@ -270,8 +270,8 @@ class ServerHttpBasicDslTests {
open class MockServerAuthenticationFailureHandler: ServerAuthenticationFailureHandler { open class MockServerAuthenticationFailureHandler: ServerAuthenticationFailureHandler {
override fun onAuthenticationFailure( override fun onAuthenticationFailure(
webFilterExchange: WebFilterExchange?, webFilterExchange: WebFilterExchange,
exception: AuthenticationException? exception: AuthenticationException
): Mono<Void> { ): Mono<Void> {
return Mono.empty() return Mono.empty()
} }

View File

@ -18,6 +18,8 @@ package org.springframework.security.access;
import java.io.Serializable; import java.io.Serializable;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.security.access.intercept.RunAsManager; import org.springframework.security.access.intercept.RunAsManager;
import org.springframework.security.authorization.AuthorizationManager; import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.annotation.SecurityAnnotationScanner; import org.springframework.security.core.annotation.SecurityAnnotationScanner;
@ -45,6 +47,7 @@ import org.springframework.security.core.annotation.SecurityAnnotationScanner;
* {@link AuthorizationManager}. * {@link AuthorizationManager}.
*/ */
@Deprecated @Deprecated
@NullUnmarked
public interface ConfigAttribute extends Serializable { public interface ConfigAttribute extends Serializable {
/** /**

View File

@ -177,7 +177,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
this.trustResolver = trustResolver; this.trustResolver = trustResolver;
} }
public void setRoleHierarchy(RoleHierarchy roleHierarchy) { public void setRoleHierarchy(@Nullable RoleHierarchy roleHierarchy) {
this.roleHierarchy = roleHierarchy; this.roleHierarchy = roleHierarchy;
} }

View File

@ -85,6 +85,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
} }
@Override @Override
@SuppressWarnings("NullAway") // FIXME: Dataflow analysis limitation
public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication, public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
MethodInvocation mi) { MethodInvocation mi) {
MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi); MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);

View File

@ -18,6 +18,8 @@ package org.springframework.security.access.vote;
import java.util.Collection; import java.util.Collection;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.security.access.AccessDecisionVoter; import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -53,6 +55,7 @@ import org.springframework.security.core.GrantedAuthority;
* instead * instead
*/ */
@Deprecated @Deprecated
@NullUnmarked
public class RoleVoter implements AccessDecisionVoter<Object> { public class RoleVoter implements AccessDecisionVoter<Object> {
private String rolePrefix = "ROLE_"; private String rolePrefix = "ROLE_";

View File

@ -18,6 +18,7 @@ package org.springframework.security.authentication;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.lang.Contract;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
/** /**
@ -80,6 +81,7 @@ public interface AuthenticationTrustResolver {
* {@link Authentication#isAuthenticated()} is true. * {@link Authentication#isAuthenticated()} is true.
* @since 6.1.7 * @since 6.1.7
*/ */
@Contract("null -> false")
default boolean isAuthenticated(@Nullable Authentication authentication) { default boolean isAuthenticated(@Nullable Authentication authentication) {
return authentication != null && authentication.isAuthenticated() && !isAnonymous(authentication); return authentication != null && authentication.isAuthenticated() && !isAnonymous(authentication);
} }

View File

@ -39,7 +39,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
private static final long serialVersionUID = 620L; private static final long serialVersionUID = 620L;
private final Object principal; private final @Nullable Object principal;
private @Nullable Object credentials; private @Nullable Object credentials;
@ -49,7 +49,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
* will return <code>false</code>. * will return <code>false</code>.
* *
*/ */
public UsernamePasswordAuthenticationToken(Object principal, @Nullable Object credentials) { public UsernamePasswordAuthenticationToken(@Nullable Object principal, @Nullable Object credentials) {
super(null); super(null);
this.principal = principal; this.principal = principal;
this.credentials = credentials; this.credentials = credentials;
@ -82,7 +82,8 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
* *
* @since 5.7 * @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); return new UsernamePasswordAuthenticationToken(principal, credentials);
} }
@ -106,7 +107,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
} }
@Override @Override
public Object getPrincipal() { public @Nullable Object getPrincipal() {
return this.principal; return this.principal;
} }

View File

@ -178,8 +178,10 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
// applied. // applied.
authorities = getAuthorities(principals); authorities = getAuthorities(principals);
// Convert the authorities set back to an array and apply it to the token. // Convert the authorities set back to an array and apply it to the token.
JaasAuthenticationToken result = new JaasAuthenticationToken(request.getPrincipal(), Object principal = request.getPrincipal();
request.getCredentials(), new ArrayList<>(authorities), loginContext); Assert.notNull(principal, "The principal cannot be null");
JaasAuthenticationToken result = new JaasAuthenticationToken(principal, request.getCredentials(),
new ArrayList<>(authorities), loginContext);
// Publish the success event // Publish the success event
publishSuccessEvent(result); publishSuccessEvent(result);
// we're done, return the token. // we're done, return the token.

View File

@ -71,8 +71,8 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
* @deprecated Please use constructor that takes a {@link String} instead * @deprecated Please use constructor that takes a {@link String} instead
*/ */
@Deprecated(forRemoval = true, since = "7.0") @Deprecated(forRemoval = true, since = "7.0")
public static OneTimeTokenAuthenticationToken unauthenticated(String tokenValue) { public static OneTimeTokenAuthenticationToken unauthenticated(@Nullable String tokenValue) {
return new OneTimeTokenAuthenticationToken(null, tokenValue); return new OneTimeTokenAuthenticationToken(null, (tokenValue != null) ? tokenValue : "");
} }
/** /**

View File

@ -18,6 +18,8 @@ package org.springframework.security.authorization;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authorization.event.AuthorizationDeniedEvent; import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
import org.springframework.security.authorization.event.AuthorizationGrantedEvent; import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -46,6 +48,7 @@ public interface AuthorizationEventPublisher {
* @param <T> the secured object's type * @param <T> the secured object's type
* @since 6.4 * @since 6.4
*/ */
<T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object, AuthorizationResult result); <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
@Nullable AuthorizationResult result);
} }

View File

@ -19,6 +19,8 @@ package org.springframework.security.authorization;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.authorization.event.AuthorizationDeniedEvent; import org.springframework.security.authorization.event.AuthorizationDeniedEvent;
import org.springframework.security.authorization.event.AuthorizationGrantedEvent; import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
@ -57,7 +59,7 @@ public final class SpringAuthorizationEventPublisher implements AuthorizationEve
*/ */
@Override @Override
public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object, public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
AuthorizationResult result) { @Nullable AuthorizationResult result) {
if (result == null) { if (result == null) {
return; return;
} }

View File

@ -74,6 +74,7 @@ public final class MethodExpressionAuthorizationManager implements Authorization
* expression * expression
*/ */
@Override @Override
@SuppressWarnings("NullAway") // FIXME: Dataflow analysis limitation
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
MethodInvocation context) { MethodInvocation context) {
EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context); EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context);

View File

@ -18,6 +18,8 @@ package org.springframework.security.authorization.method;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authorization.AuthorizationEventPublisher; import org.springframework.security.authorization.AuthorizationEventPublisher;
import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -32,7 +34,7 @@ final class NoOpAuthorizationEventPublisher implements AuthorizationEventPublish
@Override @Override
public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object, public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
AuthorizationResult result) { @Nullable AuthorizationResult result) {
} }

View File

@ -76,7 +76,7 @@ public abstract class AuthenticationException extends RuntimeException {
* authentication attempt * authentication attempt
* @since 6.5 * @since 6.5
*/ */
public void setAuthenticationRequest(Authentication authenticationRequest) { public void setAuthenticationRequest(@Nullable Authentication authenticationRequest) {
Assert.notNull(authenticationRequest, "authenticationRequest cannot be null"); Assert.notNull(authenticationRequest, "authenticationRequest cannot be null");
this.authenticationRequest = authenticationRequest; this.authenticationRequest = authenticationRequest;
} }

View File

@ -1,3 +1,7 @@
plugins {
id 'security-nullability'
}
apply plugin: 'io.spring.convention.spring-module' apply plugin: 'io.spring.convention.spring-module'
configurations { configurations {

View File

@ -24,6 +24,7 @@ import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
@ -51,9 +52,9 @@ public final class DefaultSecurityFilterChain implements SecurityFilterChain, Be
private final List<Filter> filters; private final List<Filter> filters;
private String beanName; private @Nullable String beanName;
private ConfigurableListableBeanFactory beanFactory; private @Nullable ConfigurableListableBeanFactory beanFactory;
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) { public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
this(requestMatcher, Arrays.asList(filters)); this(requestMatcher, Arrays.asList(filters));

View File

@ -30,6 +30,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@ -164,6 +165,7 @@ public class FilterChainProxy extends GenericFilterBean {
private FilterChainDecorator filterChainDecorator = new VirtualFilterChainDecorator(); private FilterChainDecorator filterChainDecorator = new VirtualFilterChainDecorator();
public FilterChainProxy() { public FilterChainProxy() {
this(Collections.emptyList());
} }
public FilterChainProxy(SecurityFilterChain chain) { public FilterChainProxy(SecurityFilterChain chain) {
@ -171,6 +173,7 @@ public class FilterChainProxy extends GenericFilterBean {
} }
public FilterChainProxy(List<SecurityFilterChain> filterChains) { public FilterChainProxy(List<SecurityFilterChain> filterChains) {
Assert.notNull(filterChains, "filterChains cannot be null");
this.filterChains = filterChains; this.filterChains = filterChains;
} }
@ -239,7 +242,7 @@ public class FilterChainProxy extends GenericFilterBean {
* @param request the request to match * @param request the request to match
* @return an ordered array of Filters defining the filter chain * @return an ordered array of Filters defining the filter chain
*/ */
private List<Filter> getFilters(HttpServletRequest request) { private @Nullable List<Filter> getFilters(HttpServletRequest request) {
int count = 0; int count = 0;
for (SecurityFilterChain chain : this.filterChains) { for (SecurityFilterChain chain : this.filterChains) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
@ -258,7 +261,7 @@ public class FilterChainProxy extends GenericFilterBean {
* @param url the URL * @param url the URL
* @return matching filter list * @return matching filter list
*/ */
public List<Filter> getFilters(String url) { public @Nullable List<Filter> getFilters(String url) {
PathPatternRequestTransformer requestTransformer = new PathPatternRequestTransformer(); PathPatternRequestTransformer requestTransformer = new PathPatternRequestTransformer();
HttpServletRequest transformed = requestTransformer.transform(new FilterInvocation(url, "GET").getRequest()); HttpServletRequest transformed = requestTransformer.transform(new FilterInvocation(url, "GET").getRequest());
return getFilters(this.firewall.getFirewalledRequest(transformed)); return getFilters(this.firewall.getFirewalledRequest(transformed));

View File

@ -36,6 +36,7 @@ import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper; import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.security.web.util.UrlUtils; import org.springframework.security.web.util.UrlUtils;
@ -62,11 +63,11 @@ public class FilterInvocation {
throw new UnsupportedOperationException("Dummy filter chain"); throw new UnsupportedOperationException("Dummy filter chain");
}; };
private FilterChain chain; private final FilterChain chain;
private HttpServletRequest request; private HttpServletRequest request;
private HttpServletResponse response; private @Nullable HttpServletResponse response;
public FilterInvocation(ServletRequest request, ServletResponse response, FilterChain chain) { public FilterInvocation(ServletRequest request, ServletResponse response, FilterChain chain) {
Assert.isTrue(request != null && response != null && chain != null, "Cannot pass null values to constructor"); Assert.isTrue(request != null && response != null && chain != null, "Cannot pass null values to constructor");
@ -79,11 +80,12 @@ public class FilterInvocation {
this(null, servletPath, method); this(null, servletPath, method);
} }
public FilterInvocation(String contextPath, String servletPath, String method) { public FilterInvocation(@Nullable String contextPath, String servletPath, String method) {
this(contextPath, servletPath, method, null); this(contextPath, servletPath, method, null);
} }
public FilterInvocation(String contextPath, String servletPath, String method, ServletContext servletContext) { public FilterInvocation(@Nullable String contextPath, String servletPath, @Nullable String method,
@Nullable ServletContext servletContext) {
this(contextPath, servletPath, null, null, method, servletContext); this(contextPath, servletPath, null, null, method, servletContext);
} }
@ -91,8 +93,8 @@ public class FilterInvocation {
this(contextPath, servletPath, pathInfo, query, method, null); this(contextPath, servletPath, pathInfo, query, method, null);
} }
public FilterInvocation(String contextPath, String servletPath, String pathInfo, String query, String method, public FilterInvocation(@Nullable String contextPath, String servletPath, @Nullable String pathInfo,
ServletContext servletContext) { @Nullable String query, @Nullable String method, @Nullable ServletContext servletContext) {
DummyRequest request = new DummyRequest(); DummyRequest request = new DummyRequest();
contextPath = (contextPath != null) ? contextPath : "/cp"; contextPath = (contextPath != null) ? contextPath : "/cp";
request.setContextPath(contextPath); request.setContextPath(contextPath);
@ -103,6 +105,7 @@ public class FilterInvocation {
request.setMethod(method); request.setMethod(method);
request.setServletContext(servletContext); request.setServletContext(servletContext);
this.request = request; this.request = request;
this.chain = DUMMY_CHAIN;
} }
public FilterChain getChain() { public FilterChain getChain() {
@ -124,7 +127,7 @@ public class FilterInvocation {
return this.request; return this.request;
} }
public HttpServletResponse getHttpResponse() { public @Nullable HttpServletResponse getHttpResponse() {
return this.response; return this.response;
} }
@ -140,7 +143,7 @@ public class FilterInvocation {
return getHttpRequest(); return getHttpRequest();
} }
public HttpServletResponse getResponse() { public @Nullable HttpServletResponse getResponse() {
return getHttpResponse(); return getHttpResponse();
} }
@ -160,19 +163,19 @@ public class FilterInvocation {
DummyRequest.class.getClassLoader(), new Class[] { HttpServletRequest.class }, DummyRequest.class.getClassLoader(), new Class[] { HttpServletRequest.class },
new UnsupportedOperationExceptionInvocationHandler()); new UnsupportedOperationExceptionInvocationHandler());
private String requestURI; private @Nullable String requestURI;
private String contextPath = ""; private String contextPath = "";
private String servletPath; private @Nullable String servletPath;
private String pathInfo; private @Nullable String pathInfo;
private String queryString; private @Nullable String queryString;
private String method; private @Nullable String method;
private ServletContext servletContext; private @Nullable ServletContext servletContext;
private final HttpHeaders headers = new HttpHeaders(); private final HttpHeaders headers = new HttpHeaders();
@ -188,7 +191,7 @@ public class FilterInvocation {
} }
@Override @Override
public Object getAttribute(String attributeName) { public @Nullable Object getAttribute(String attributeName) {
return null; return null;
} }
@ -196,12 +199,12 @@ public class FilterInvocation {
this.requestURI = requestURI; this.requestURI = requestURI;
} }
void setPathInfo(String pathInfo) { void setPathInfo(@Nullable String pathInfo) {
this.pathInfo = pathInfo; this.pathInfo = pathInfo;
} }
@Override @Override
public String getRequestURI() { public @Nullable String getRequestURI() {
return this.requestURI; return this.requestURI;
} }
@ -219,40 +222,40 @@ public class FilterInvocation {
} }
@Override @Override
public String getServletPath() { public @Nullable String getServletPath() {
return this.servletPath; return this.servletPath;
} }
void setMethod(String method) { void setMethod(@Nullable String method) {
this.method = method; this.method = method;
} }
@Override @Override
public String getMethod() { public @Nullable String getMethod() {
return this.method; return this.method;
} }
@Override @Override
public String getPathInfo() { public @Nullable String getPathInfo() {
return this.pathInfo; return this.pathInfo;
} }
@Override @Override
public String getQueryString() { public @Nullable String getQueryString() {
return this.queryString; return this.queryString;
} }
void setQueryString(String queryString) { void setQueryString(@Nullable String queryString) {
this.queryString = queryString; this.queryString = queryString;
} }
@Override @Override
public String getServerName() { public @Nullable String getServerName() {
return null; return null;
} }
@Override @Override
public String getHeader(String name) { public @Nullable String getHeader(String name) {
return this.headers.getFirst(name); return this.headers.getFirst(name);
} }
@ -284,7 +287,7 @@ public class FilterInvocation {
} }
@Override @Override
public String getParameter(String name) { public @Nullable String getParameter(String name) {
String[] array = this.parameters.get(name); String[] array = this.parameters.get(name);
return (array != null && array.length > 0) ? array[0] : null; return (array != null && array.length > 0) ? array[0] : null;
} }
@ -300,7 +303,7 @@ public class FilterInvocation {
} }
@Override @Override
public String[] getParameterValues(String name) { public String @Nullable [] getParameterValues(String name) {
return this.parameters.get(name); return this.parameters.get(name);
} }
@ -309,11 +312,11 @@ public class FilterInvocation {
} }
@Override @Override
public ServletContext getServletContext() { public @Nullable ServletContext getServletContext() {
return this.servletContext; return this.servletContext;
} }
void setServletContext(ServletContext servletContext) { void setServletContext(@Nullable ServletContext servletContext) {
this.servletContext = servletContext; this.servletContext = servletContext;
} }

View File

@ -37,6 +37,8 @@ import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -49,6 +51,7 @@ import org.springframework.util.StringUtils;
* @author Nikita Konev * @author Nikita Konev
* @since 6.0 * @since 6.0
*/ */
@NullUnmarked // https://github.com/spring-projects/spring-security/issues/17815
public final class ObservationFilterChainDecorator implements FilterChainProxy.FilterChainDecorator { public final class ObservationFilterChainDecorator implements FilterChainProxy.FilterChainDecorator {
private static final Log logger = LogFactory.getLog(FilterChainProxy.class); private static final Log logger = LogFactory.getLog(FilterChainProxy.class);
@ -507,7 +510,7 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
private final String filterSection; private final String filterSection;
private String filterName; private @Nullable String filterName;
private int chainPosition; private int chainPosition;
@ -530,7 +533,7 @@ public final class ObservationFilterChainDecorator implements FilterChainProxy.F
return this.filterSection; return this.filterSection;
} }
String getFilterName() { @Nullable String getFilterName() {
return this.filterName; return this.filterName;
} }

View File

@ -16,6 +16,8 @@
package org.springframework.security.web; package org.springframework.security.web;
import org.jspecify.annotations.Nullable;
/** /**
* <code>PortMapper</code> implementations provide callers with information about which * <code>PortMapper</code> implementations provide callers with information about which
* HTTP ports are associated with which HTTPS ports on the system, and vice versa. * HTTP ports are associated with which HTTPS ports on the system, and vice versa.
@ -32,7 +34,7 @@ public interface PortMapper {
* @param httpsPort * @param httpsPort
* @return the HTTP port or <code>null</code> if unknown * @return the HTTP port or <code>null</code> if unknown
*/ */
Integer lookupHttpPort(Integer httpsPort); @Nullable Integer lookupHttpPort(Integer httpsPort);
/** /**
* Locates the HTTPS port associated with the specified HTTP port. * Locates the HTTPS port associated with the specified HTTP port.
@ -42,6 +44,6 @@ public interface PortMapper {
* @param httpPort * @param httpPort
* @return the HTTPS port or <code>null</code> if unknown * @return the HTTPS port or <code>null</code> if unknown
*/ */
Integer lookupHttpsPort(Integer httpPort); @Nullable Integer lookupHttpsPort(Integer httpPort);
} }

View File

@ -19,6 +19,8 @@ package org.springframework.security.web;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -50,7 +52,7 @@ public class PortMapperImpl implements PortMapper {
} }
@Override @Override
public Integer lookupHttpPort(Integer httpsPort) { public @Nullable Integer lookupHttpPort(Integer httpsPort) {
for (Integer httpPort : this.httpsPortMappings.keySet()) { for (Integer httpPort : this.httpsPortMappings.keySet()) {
if (this.httpsPortMappings.get(httpPort).equals(httpsPort)) { if (this.httpsPortMappings.get(httpPort).equals(httpsPort)) {
return httpPort; return httpPort;
@ -60,7 +62,7 @@ public class PortMapperImpl implements PortMapper {
} }
@Override @Override
public Integer lookupHttpsPort(Integer httpPort) { public @Nullable Integer lookupHttpsPort(Integer httpPort) {
return this.httpsPortMappings.get(httpPort); return this.httpsPortMappings.get(httpPort);
} }

View File

@ -19,6 +19,7 @@ package org.springframework.security.web;
import java.util.Locale; import java.util.Locale;
import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -54,7 +55,7 @@ public class PortResolverImpl implements PortResolver {
return (mappedPort != null) ? mappedPort : serverPort; return (mappedPort != null) ? mappedPort : serverPort;
} }
private Integer getMappedPort(int serverPort, String scheme) { private @Nullable Integer getMappedPort(int serverPort, String scheme) {
if ("http".equals(scheme)) { if ("http".equals(scheme)) {
return this.portMapper.lookupHttpPort(serverPort); return this.portMapper.lookupHttpPort(serverPort);
} }

View File

@ -23,6 +23,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -47,7 +48,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
protected static final Log logger = LogFactory.getLog(AccessDeniedHandlerImpl.class); protected static final Log logger = LogFactory.getLog(AccessDeniedHandlerImpl.class);
private String errorPage; private @Nullable String errorPage;
@Override @Override
public void handle(HttpServletRequest request, HttpServletResponse response, public void handle(HttpServletRequest request, HttpServletResponse response,

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.access;
import jakarta.servlet.ServletContext; import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authorization.AuthorizationManager; import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.authorization.AuthorizationResult;
@ -38,7 +39,7 @@ public final class AuthorizationManagerWebInvocationPrivilegeEvaluator
private final AuthorizationManager<HttpServletRequest> authorizationManager; private final AuthorizationManager<HttpServletRequest> authorizationManager;
private ServletContext servletContext; private @Nullable ServletContext servletContext;
private HttpServletRequestTransformer requestTransformer = HttpServletRequestTransformer.IDENTITY; private HttpServletRequestTransformer requestTransformer = HttpServletRequestTransformer.IDENTITY;
@ -54,7 +55,8 @@ public final class AuthorizationManagerWebInvocationPrivilegeEvaluator
} }
@Override @Override
public boolean isAllowed(String contextPath, String uri, String method, Authentication authentication) { public boolean isAllowed(@Nullable String contextPath, String uri, @Nullable String method,
Authentication authentication) {
FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext); FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext);
HttpServletRequest httpRequest = this.requestTransformer.transform(filterInvocation.getHttpRequest()); HttpServletRequest httpRequest = this.requestTransformer.transform(filterInvocation.getHttpRequest());
AuthorizationResult result = this.authorizationManager.authorize(() -> authentication, httpRequest); AuthorizationResult result = this.authorizationManager.authorize(() -> authentication, httpRequest);

View File

@ -21,6 +21,7 @@ import java.util.Collection;
import jakarta.servlet.ServletContext; import jakarta.servlet.ServletContext;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
@ -46,7 +47,7 @@ public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPriv
private final AbstractSecurityInterceptor securityInterceptor; private final AbstractSecurityInterceptor securityInterceptor;
private ServletContext servletContext; private @Nullable ServletContext servletContext;
public DefaultWebInvocationPrivilegeEvaluator(AbstractSecurityInterceptor securityInterceptor) { public DefaultWebInvocationPrivilegeEvaluator(AbstractSecurityInterceptor securityInterceptor) {
Assert.notNull(securityInterceptor, "SecurityInterceptor cannot be null"); Assert.notNull(securityInterceptor, "SecurityInterceptor cannot be null");
@ -86,7 +87,8 @@ public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPriv
* @return true if access is allowed, false if denied * @return true if access is allowed, false if denied
*/ */
@Override @Override
public boolean isAllowed(String contextPath, String uri, String method, Authentication authentication) { public boolean isAllowed(@Nullable String contextPath, String uri, @Nullable String method,
Authentication authentication) {
Assert.notNull(uri, "uri parameter is required"); Assert.notNull(uri, "uri parameter is required");
FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext); FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext);
Collection<ConfigAttribute> attributes = this.securityInterceptor.obtainSecurityMetadataSource() Collection<ConfigAttribute> attributes = this.securityInterceptor.obtainSecurityMetadataSource()

View File

@ -24,6 +24,7 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse; import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware; import org.springframework.context.MessageSourceAware;
@ -169,7 +170,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean implements Mes
} }
private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response, private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, RuntimeException exception) throws IOException, ServletException { FilterChain chain, @Nullable RuntimeException exception) throws IOException, ServletException {
if (exception instanceof AuthenticationException) { if (exception instanceof AuthenticationException) {
handleAuthenticationException(request, response, chain, (AuthenticationException) exception); handleAuthenticationException(request, response, chain, (AuthenticationException) exception);
} }

View File

@ -21,6 +21,7 @@ import java.util.Map;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper; import jakarta.servlet.http.HttpServletRequestWrapper;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.web.util.ServletRequestPathUtils; import org.springframework.web.util.ServletRequestPathUtils;
@ -51,7 +52,7 @@ public final class PathPatternRequestTransformer
} }
@Override @Override
public Object getAttribute(String name) { public @Nullable Object getAttribute(String name) {
return this.attributes.get(name); return this.attributes.get(name);
} }

View File

@ -21,6 +21,7 @@ import java.util.List;
import jakarta.servlet.ServletContext; import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authorization.AuthorizationManager; import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -46,7 +47,7 @@ public final class RequestMatcherDelegatingWebInvocationPrivilegeEvaluator
private final List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> delegates; private final List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> delegates;
private ServletContext servletContext; private @Nullable ServletContext servletContext;
public RequestMatcherDelegatingWebInvocationPrivilegeEvaluator( public RequestMatcherDelegatingWebInvocationPrivilegeEvaluator(
List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> requestMatcherPrivilegeEvaluatorsEntries) { List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> requestMatcherPrivilegeEvaluatorsEntries) {
@ -119,7 +120,8 @@ public final class RequestMatcherDelegatingWebInvocationPrivilegeEvaluator
return true; return true;
} }
private List<WebInvocationPrivilegeEvaluator> getDelegate(String contextPath, String uri, String method) { private List<WebInvocationPrivilegeEvaluator> getDelegate(@Nullable String contextPath, String uri,
@Nullable String method) {
FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext); FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext);
HttpServletRequest request = filterInvocation.getHttpRequest(); HttpServletRequest request = filterInvocation.getHttpRequest();
for (RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>> delegate : this.delegates) { for (RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>> delegate : this.delegates) {

View File

@ -22,6 +22,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.DefaultRedirectStrategy;
@ -79,7 +80,7 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
this.redirectStrategy.sendRedirect(request, response, redirectUrl); this.redirectStrategy.sendRedirect(request, response, redirectUrl);
} }
protected abstract Integer getMappedPort(Integer mapFromPort); protected abstract @Nullable Integer getMappedPort(Integer mapFromPort);
protected final PortMapper getPortMapper() { protected final PortMapper getPortMapper() {
return this.portMapper; return this.portMapper;

View File

@ -22,6 +22,8 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
@ -49,6 +51,7 @@ import org.springframework.util.Assert;
* {@link RequestMatcher} for any sophisticated decision-making * {@link RequestMatcher} for any sophisticated decision-making
*/ */
@Deprecated @Deprecated
@NullUnmarked
public class ChannelDecisionManagerImpl implements ChannelDecisionManager, InitializingBean { public class ChannelDecisionManagerImpl implements ChannelDecisionManager, InitializingBean {
public static final String ANY_CHANNEL = "ANY_CHANNEL"; public static final String ANY_CHANNEL = "ANY_CHANNEL";
@ -76,7 +79,7 @@ public class ChannelDecisionManagerImpl implements ChannelDecisionManager, Initi
} }
} }
protected List<ChannelProcessor> getChannelProcessors() { protected @Nullable List<ChannelProcessor> getChannelProcessors() {
return this.channelProcessors; return this.channelProcessors;
} }

View File

@ -27,6 +27,7 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse; import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
@ -88,8 +89,10 @@ import org.springframework.web.filter.GenericFilterBean;
@Deprecated @Deprecated
public class ChannelProcessingFilter extends GenericFilterBean { public class ChannelProcessingFilter extends GenericFilterBean {
@SuppressWarnings("NullAway.Init")
private ChannelDecisionManager channelDecisionManager; private ChannelDecisionManager channelDecisionManager;
@SuppressWarnings("NullAway.Init")
private FilterInvocationSecurityMetadataSource securityMetadataSource; private FilterInvocationSecurityMetadataSource securityMetadataSource;
@Override @Override
@ -128,14 +131,16 @@ public class ChannelProcessingFilter extends GenericFilterBean {
if (attributes != null) { if (attributes != null) {
this.logger.debug(LogMessage.format("Request: %s; ConfigAttributes: %s", filterInvocation, attributes)); this.logger.debug(LogMessage.format("Request: %s; ConfigAttributes: %s", filterInvocation, attributes));
this.channelDecisionManager.decide(filterInvocation, attributes); this.channelDecisionManager.decide(filterInvocation, attributes);
if (filterInvocation.getResponse().isCommitted()) { @Nullable HttpServletResponse channelResponse = filterInvocation.getResponse();
Assert.notNull(channelResponse, "HttpServletResponse is required");
if (channelResponse.isCommitted()) {
return; return;
} }
} }
chain.doFilter(request, response); chain.doFilter(request, response);
} }
protected ChannelDecisionManager getChannelDecisionManager() { protected @Nullable ChannelDecisionManager getChannelDecisionManager() {
return this.channelDecisionManager; return this.channelDecisionManager;
} }

View File

@ -20,6 +20,8 @@ import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
@ -63,7 +65,9 @@ public class InsecureChannelProcessor implements InitializingBean, ChannelProces
for (ConfigAttribute attribute : config) { for (ConfigAttribute attribute : config) {
if (supports(attribute)) { if (supports(attribute)) {
if (invocation.getHttpRequest().isSecure()) { if (invocation.getHttpRequest().isSecure()) {
this.entryPoint.commence(invocation.getRequest(), invocation.getResponse()); @Nullable HttpServletResponse response = invocation.getResponse();
Assert.notNull(response, "HttpServletResponse required");
this.entryPoint.commence(invocation.getRequest(), response);
} }
} }
} }

View File

@ -16,6 +16,8 @@
package org.springframework.security.web.access.channel; package org.springframework.security.web.access.channel;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.PortMapper; import org.springframework.security.web.PortMapper;
/** /**
@ -38,7 +40,7 @@ public class RetryWithHttpEntryPoint extends AbstractRetryEntryPoint {
} }
@Override @Override
protected Integer getMappedPort(Integer mapFromPort) { protected @Nullable Integer getMappedPort(Integer mapFromPort) {
return getPortMapper().lookupHttpPort(mapFromPort); return getPortMapper().lookupHttpPort(mapFromPort);
} }

View File

@ -16,6 +16,8 @@
package org.springframework.security.web.access.channel; package org.springframework.security.web.access.channel;
import org.jspecify.annotations.Nullable;
import org.springframework.security.web.PortMapper; import org.springframework.security.web.PortMapper;
/** /**
@ -39,7 +41,7 @@ public class RetryWithHttpsEntryPoint extends AbstractRetryEntryPoint {
} }
@Override @Override
protected Integer getMappedPort(Integer mapFromPort) { protected @Nullable Integer getMappedPort(Integer mapFromPort) {
return getPortMapper().lookupHttpsPort(mapFromPort); return getPortMapper().lookupHttpsPort(mapFromPort);
} }

View File

@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
@ -63,7 +64,9 @@ public class SecureChannelProcessor implements InitializingBean, ChannelProcesso
for (ConfigAttribute attribute : config) { for (ConfigAttribute attribute : config) {
if (supports(attribute)) { if (supports(attribute)) {
if (!invocation.getHttpRequest().isSecure()) { if (!invocation.getHttpRequest().isSecure()) {
this.entryPoint.commence(invocation.getRequest(), invocation.getResponse()); HttpServletResponse response = invocation.getResponse();
Assert.notNull(response, "HttpServletResponse is required");
this.entryPoint.commence(invocation.getRequest(), response);
} }
} }
} }

View File

@ -19,4 +19,7 @@
* <p> * <p>
* Most commonly used to enforce that requests are submitted over HTTP or HTTPS. * Most commonly used to enforce that requests are submitted over HTTP or HTTPS.
*/ */
@NullMarked
package org.springframework.security.web.access.channel; package org.springframework.security.web.access.channel;
import org.jspecify.annotations.NullMarked;

View File

@ -19,6 +19,7 @@ package org.springframework.security.web.access.expression;
import java.util.Map; import java.util.Map;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationContext;
import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.FilterInvocation;
@ -53,7 +54,7 @@ abstract class AbstractVariableEvaluationContextPostProcessor
private final HttpServletRequest request; private final HttpServletRequest request;
private Map<String, String> variables; private @Nullable Map<String, String> variables;
VariableEvaluationContext(EvaluationContext delegate, HttpServletRequest request) { VariableEvaluationContext(EvaluationContext delegate, HttpServletRequest request) {
super(delegate); super(delegate);
@ -61,7 +62,7 @@ abstract class AbstractVariableEvaluationContextPostProcessor
} }
@Override @Override
public Object lookupVariable(String name) { public @Nullable Object lookupVariable(String name) {
Object result = super.lookupVariable(name); Object result = super.lookupVariable(name);
if (result != null) { if (result != null) {
return result; return result;

View File

@ -46,6 +46,7 @@ public class DefaultHttpSecurityExpressionHandler extends AbstractSecurityExpres
private String defaultRolePrefix = "ROLE_"; private String defaultRolePrefix = "ROLE_";
@Override @Override
@SuppressWarnings("NullAway") // https://github.com/spring-projects/spring-framework/issues/35371
public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication, public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
RequestAuthorizationContext context) { RequestAuthorizationContext context) {
WebSecurityExpressionRoot root = createSecurityExpressionRoot(authentication, context); WebSecurityExpressionRoot root = createSecurityExpressionRoot(authentication, context);
@ -56,13 +57,13 @@ public class DefaultHttpSecurityExpressionHandler extends AbstractSecurityExpres
} }
@Override @Override
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, protected SecurityExpressionOperations createSecurityExpressionRoot(@Nullable Authentication authentication,
RequestAuthorizationContext context) { RequestAuthorizationContext context) {
return createSecurityExpressionRoot(() -> authentication, context); return createSecurityExpressionRoot(() -> authentication, context);
} }
private WebSecurityExpressionRoot createSecurityExpressionRoot(Supplier<? extends Authentication> authentication, private WebSecurityExpressionRoot createSecurityExpressionRoot(
RequestAuthorizationContext context) { Supplier<? extends @Nullable Authentication> authentication, RequestAuthorizationContext context) {
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, context.getRequest()); WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, context.getRequest());
root.setRoleHierarchy(getRoleHierarchy()); root.setRoleHierarchy(getRoleHierarchy());
root.setPermissionEvaluator(getPermissionEvaluator()); root.setPermissionEvaluator(getPermissionEvaluator());

View File

@ -16,6 +16,8 @@
package org.springframework.security.web.access.expression; package org.springframework.security.web.access.expression;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler; import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionHandler; import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionOperations; import org.springframework.security.access.expression.SecurityExpressionOperations;
@ -38,7 +40,7 @@ public class DefaultWebSecurityExpressionHandler extends AbstractSecurityExpress
private String defaultRolePrefix = "ROLE_"; private String defaultRolePrefix = "ROLE_";
@Override @Override
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, protected SecurityExpressionOperations createSecurityExpressionRoot(@Nullable Authentication authentication,
FilterInvocation fi) { FilterInvocation fi) {
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi); WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
root.setPermissionEvaluator(getPermissionEvaluator()); root.setPermissionEvaluator(getPermissionEvaluator());

View File

@ -18,6 +18,8 @@ package org.springframework.security.web.access.expression;
import java.util.List; import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.BeanResolver; import org.springframework.expression.BeanResolver;
import org.springframework.expression.ConstructorResolver; import org.springframework.expression.ConstructorResolver;
import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationContext;
@ -84,17 +86,17 @@ class DelegatingEvaluationContext implements EvaluationContext {
} }
@Override @Override
public BeanResolver getBeanResolver() { public @Nullable BeanResolver getBeanResolver() {
return this.delegate.getBeanResolver(); return this.delegate.getBeanResolver();
} }
@Override @Override
public void setVariable(String name, Object value) { public void setVariable(String name, @Nullable Object value) {
this.delegate.setVariable(name, value); this.delegate.setVariable(name, value);
} }
@Override @Override
public Object lookupVariable(String name) { public @Nullable Object lookupVariable(String name) {
return this.delegate.lookupVariable(name); return this.delegate.lookupVariable(name);
} }

View File

@ -16,6 +16,8 @@
package org.springframework.security.web.access.expression; package org.springframework.security.web.access.expression;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression; import org.springframework.expression.Expression;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
@ -32,6 +34,7 @@ import org.springframework.security.web.FilterInvocation;
* {@link AuthorizationManager}. * {@link AuthorizationManager}.
*/ */
@Deprecated @Deprecated
@NullUnmarked
class WebExpressionConfigAttribute implements ConfigAttribute, EvaluationContextPostProcessor<FilterInvocation> { class WebExpressionConfigAttribute implements ConfigAttribute, EvaluationContextPostProcessor<FilterInvocation> {
private final Expression authorizeExpression; private final Expression authorizeExpression;

View File

@ -20,6 +20,7 @@ import java.util.Collection;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationContext;
import org.springframework.security.access.AccessDecisionVoter; import org.springframework.security.access.AccessDecisionVoter;
@ -66,7 +67,7 @@ public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation>
return ACCESS_DENIED; return ACCESS_DENIED;
} }
private WebExpressionConfigAttribute findConfigAttribute(Collection<ConfigAttribute> attributes) { private @Nullable WebExpressionConfigAttribute findConfigAttribute(Collection<ConfigAttribute> attributes) {
for (ConfigAttribute attribute : attributes) { for (ConfigAttribute attribute : attributes) {
if (attribute instanceof WebExpressionConfigAttribute) { if (attribute instanceof WebExpressionConfigAttribute) {
return (WebExpressionConfigAttribute) attribute; return (WebExpressionConfigAttribute) attribute;

View File

@ -19,6 +19,7 @@ package org.springframework.security.web.access.expression;
import java.util.function.Supplier; import java.util.function.Supplier;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.expression.SecurityExpressionRoot; import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -37,7 +38,7 @@ public class WebSecurityExpressionRoot extends SecurityExpressionRoot {
*/ */
public final HttpServletRequest request; public final HttpServletRequest request;
public WebSecurityExpressionRoot(Authentication a, FilterInvocation fi) { public WebSecurityExpressionRoot(@Nullable Authentication a, FilterInvocation fi) {
this(() -> a, fi.getRequest()); this(() -> a, fi.getRequest());
} }
@ -48,7 +49,9 @@ public class WebSecurityExpressionRoot extends SecurityExpressionRoot {
* @param request the {@link HttpServletRequest} to use * @param request the {@link HttpServletRequest} to use
* @since 5.8 * @since 5.8
*/ */
public WebSecurityExpressionRoot(Supplier<? extends Authentication> authentication, HttpServletRequest request) { @SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1246
public WebSecurityExpressionRoot(Supplier<? extends @Nullable Authentication> authentication,
HttpServletRequest request) {
super(authentication); super(authentication);
this.request = request; this.request = request;
} }

View File

@ -17,4 +17,7 @@
/** /**
* Implementation of web security expressions. * Implementation of web security expressions.
*/ */
@NullMarked
package org.springframework.security.web.access.expression; package org.springframework.security.web.access.expression;
import org.jspecify.annotations.NullMarked;

View File

@ -26,6 +26,7 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse; import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
@ -202,7 +203,7 @@ public class AuthorizationFilter extends GenericFilterBean {
@Override @Override
public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object, public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
AuthorizationResult result) { @Nullable AuthorizationResult result) {
} }
} }

View File

@ -17,6 +17,7 @@
package org.springframework.security.web.access.intercept; package org.springframework.security.web.access.intercept;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@ -99,7 +100,7 @@ public class DefaultFilterInvocationSecurityMetadataSource implements FilterInvo
} }
} }
} }
return null; return Collections.emptyList();
} }
@Override @Override

View File

@ -24,6 +24,7 @@ import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse; import jakarta.servlet.ServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
@ -48,7 +49,7 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied"; private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
private FilterInvocationSecurityMetadataSource securityMetadataSource; private @Nullable FilterInvocationSecurityMetadataSource securityMetadataSource;
private boolean observeOncePerRequest = false; private boolean observeOncePerRequest = false;
@ -83,12 +84,12 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
invoke(new FilterInvocation(request, response, chain)); invoke(new FilterInvocation(request, response, chain));
} }
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() { public @Nullable FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return this.securityMetadataSource; return this.securityMetadataSource;
} }
@Override @Override
public SecurityMetadataSource obtainSecurityMetadataSource() { public @Nullable SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource; return this.securityMetadataSource;
} }

View File

@ -16,6 +16,8 @@
package org.springframework.security.web.access.intercept; package org.springframework.security.web.access.intercept;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -26,13 +28,13 @@ public class RequestKey {
private final String url; private final String url;
private final String method; private final @Nullable String method;
public RequestKey(String url) { public RequestKey(String url) {
this(url, null); this(url, null);
} }
public RequestKey(String url, String method) { public RequestKey(String url, @Nullable String method) {
Assert.notNull(url, "url cannot be null"); Assert.notNull(url, "url cannot be null");
this.url = url; this.url = url;
this.method = method; this.method = method;
@ -42,7 +44,7 @@ public class RequestKey {
return this.url; return this.url;
} }
String getMethod() { @Nullable String getMethod() {
return this.method; return this.method;
} }

View File

@ -64,7 +64,7 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho
} }
@Override @Override
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, public @Nullable AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
HttpServletRequest request) { HttpServletRequest request) {
if (this.logger.isTraceEnabled()) { if (this.logger.isTraceEnabled()) {
this.logger.trace(LogMessage.format("Authorizing %s", requestLine(request))); this.logger.trace(LogMessage.format("Authorizing %s", requestLine(request)));

View File

@ -17,4 +17,7 @@
/** /**
* Enforcement of security for HTTP requests, typically by the URL requested. * Enforcement of security for HTTP requests, typically by the URL requested.
*/ */
@NullMarked
package org.springframework.security.web.access.intercept; package org.springframework.security.web.access.intercept;
import org.jspecify.annotations.NullMarked;

View File

@ -17,4 +17,7 @@
/** /**
* Access-control related classes and packages. * Access-control related classes and packages.
*/ */
@NullMarked
package org.springframework.security.web.access; package org.springframework.security.web.access;
import org.jspecify.annotations.NullMarked;

View File

@ -16,6 +16,8 @@
package org.springframework.security.web.aot.hint; package org.springframework.security.web.aot.hint;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.RuntimeHintsRegistrar;
@ -33,7 +35,7 @@ import org.springframework.security.web.access.expression.WebSecurityExpressionR
class WebMvcSecurityRuntimeHints implements RuntimeHintsRegistrar { class WebMvcSecurityRuntimeHints implements RuntimeHintsRegistrar {
@Override @Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) { public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.reflection() hints.reflection()
.registerType(WebSecurityExpressionRoot.class, (builder) -> builder .registerType(WebSecurityExpressionRoot.class, (builder) -> builder
.withMembers(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.ACCESS_DECLARED_FIELDS)); .withMembers(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.ACCESS_DECLARED_FIELDS));

View File

@ -0,0 +1,23 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Runtime hints for AOT web package.
*/
@NullMarked
package org.springframework.security.web.aot.hint;
import org.jspecify.annotations.NullMarked;

View File

@ -24,6 +24,7 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse; import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationEventPublisherAware;
@ -120,7 +121,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy(); .getContextHolderStrategy();
protected ApplicationEventPublisher eventPublisher; @Nullable protected ApplicationEventPublisher eventPublisher;
protected AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource(); protected AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
@ -129,6 +130,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
"Please either configure an AuthenticationConverter or override attemptAuthentication when extending AbstractAuthenticationProcessingFilter"); "Please either configure an AuthenticationConverter or override attemptAuthentication when extending AbstractAuthenticationProcessingFilter");
}; };
@SuppressWarnings("NullAway.Init")
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
@ -155,7 +157,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
* @param defaultFilterProcessesUrl the default value for <tt>filterProcessesUrl</tt>. * @param defaultFilterProcessesUrl the default value for <tt>filterProcessesUrl</tt>.
*/ */
protected AbstractAuthenticationProcessingFilter(String defaultFilterProcessesUrl) { protected AbstractAuthenticationProcessingFilter(String defaultFilterProcessesUrl) {
setFilterProcessesUrl(defaultFilterProcessesUrl); this(pathPattern(defaultFilterProcessesUrl));
} }
/** /**
@ -177,7 +179,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
*/ */
protected AbstractAuthenticationProcessingFilter(String defaultFilterProcessesUrl, protected AbstractAuthenticationProcessingFilter(String defaultFilterProcessesUrl,
AuthenticationManager authenticationManager) { AuthenticationManager authenticationManager) {
setFilterProcessesUrl(defaultFilterProcessesUrl); this(pathPattern(defaultFilterProcessesUrl));
setAuthenticationManager(authenticationManager); setAuthenticationManager(authenticationManager);
} }
@ -305,7 +307,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
* @return the authenticated user token, or null if authentication is incomplete. * @return the authenticated user token, or null if authentication is incomplete.
* @throws AuthenticationException if authentication fails. * @throws AuthenticationException if authentication fails.
*/ */
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) public @Nullable Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException { throws AuthenticationException, IOException, ServletException {
Authentication authentication = this.authenticationConverter.convert(request); Authentication authentication = this.authenticationConverter.convert(request);
if (authentication == null) { if (authentication == null) {

View File

@ -23,6 +23,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -62,7 +63,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
protected final Log logger = LogFactory.getLog(this.getClass()); protected final Log logger = LogFactory.getLog(this.getClass());
private String targetUrlParameter = null; private @Nullable String targetUrlParameter = null;
private String defaultTargetUrl = "/"; private String defaultTargetUrl = "/";
@ -81,8 +82,8 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
* <p> * <p>
* The redirect will not be performed if the response has already been committed. * The redirect will not be performed if the response has already been committed.
*/ */
protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication) protected void handle(HttpServletRequest request, HttpServletResponse response,
throws IOException, ServletException { @Nullable Authentication authentication) throws IOException, ServletException {
String targetUrl = determineTargetUrl(request, response, authentication); String targetUrl = determineTargetUrl(request, response, authentication);
if (response.isCommitted()) { if (response.isCommitted()) {
this.logger.debug(LogMessage.format("Did not redirect to %s since response already committed.", targetUrl)); this.logger.debug(LogMessage.format("Did not redirect to %s since response already committed.", targetUrl));
@ -96,7 +97,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
* @since 5.2 * @since 5.2
*/ */
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) { @Nullable Authentication authentication) {
return determineTargetUrl(request, response); return determineTargetUrl(request, response);
} }
@ -119,7 +120,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
return this.defaultTargetUrl; return this.defaultTargetUrl;
} }
private String getTargetUrlParameterValue(HttpServletRequest request) { private @Nullable String getTargetUrlParameterValue(HttpServletRequest request) {
if (this.targetUrlParameter == null) { if (this.targetUrlParameter == null) {
return null; return null;
} }
@ -133,7 +134,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
return this.defaultTargetUrl; return this.defaultTargetUrl;
} }
private void trace(String msg, String... msgParts) { private void trace(String msg, @Nullable String... msgParts) {
if (this.logger.isTraceEnabled()) { if (this.logger.isTraceEnabled()) {
this.logger.trace(LogMessage.format(msg, msgParts)); this.logger.trace(LogMessage.format(msg, msgParts));
} }
@ -189,7 +190,7 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
this.targetUrlParameter = targetUrlParameter; this.targetUrlParameter = targetUrlParameter;
} }
protected String getTargetUrlParameter() { protected @Nullable String getTargetUrlParameter() {
return this.targetUrlParameter; return this.targetUrlParameter;
} }

View File

@ -17,6 +17,7 @@
package org.springframework.security.web.authentication; package org.springframework.security.web.authentication;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -35,6 +36,6 @@ import org.springframework.security.core.AuthenticationException;
*/ */
public interface AuthenticationConverter { public interface AuthenticationConverter {
Authentication convert(HttpServletRequest request); @Nullable Authentication convert(HttpServletRequest request);
} }

View File

@ -24,6 +24,7 @@ import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
@ -218,7 +219,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
this.successHandler.onAuthenticationSuccess(request, response, chain, authentication); this.successHandler.onAuthenticationSuccess(request, response, chain, authentication);
} }
private Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) private @Nullable Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, ServletException { throws AuthenticationException, ServletException {
Authentication authentication = this.authenticationConverter.convert(request); Authentication authentication = this.authenticationConverter.convert(request);
if (authentication == null) { if (authentication == null) {

View File

@ -19,6 +19,7 @@ package org.springframework.security.web.authentication;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -46,7 +47,7 @@ public final class DelegatingAuthenticationConverter implements AuthenticationCo
} }
@Override @Override
public Authentication convert(HttpServletRequest request) { public @Nullable Authentication convert(HttpServletRequest request) {
for (AuthenticationConverter delegate : this.delegates) { for (AuthenticationConverter delegate : this.delegates) {
Authentication authentication = delegate.convert(request); Authentication authentication = delegate.convert(request);
if (authentication != null) { if (authentication != null) {

View File

@ -66,6 +66,7 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo
private final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints; private final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints;
@SuppressWarnings("NullAway.Init")
private AuthenticationEntryPoint defaultEntryPoint; private AuthenticationEntryPoint defaultEntryPoint;
public DelegatingAuthenticationEntryPoint(LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) { public DelegatingAuthenticationEntryPoint(LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) {

View File

@ -24,6 +24,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
@ -187,7 +188,8 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
* Builds a URL to redirect the supplied request to HTTPS. Used to redirect the * Builds a URL to redirect the supplied request to HTTPS. Used to redirect the
* current request to HTTPS, before doing a forward to the login page. * current request to HTTPS, before doing a forward to the login page.
*/ */
protected String buildHttpsRedirectUrlForRequest(HttpServletRequest request) throws IOException, ServletException { protected @Nullable String buildHttpsRedirectUrlForRequest(HttpServletRequest request)
throws IOException, ServletException {
int serverPort = this.portResolver.getServerPort(request); int serverPort = this.portResolver.getServerPort(request);
Integer httpsPort = this.portMapper.lookupHttpsPort(serverPort); Integer httpsPort = this.portMapper.lookupHttpsPort(serverPort);
if (httpsPort != null) { if (httpsPort != null) {

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.authentication;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -32,7 +33,7 @@ import org.springframework.security.core.Authentication;
public class NullRememberMeServices implements RememberMeServices { public class NullRememberMeServices implements RememberMeServices {
@Override @Override
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { public @Nullable Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
return null; return null;
} }

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.authentication;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -69,7 +70,7 @@ public interface RememberMeServices {
* @return a valid authentication object, or <code>null</code> if the request should * @return a valid authentication object, or <code>null</code> if the request should
* not be authenticated * not be authenticated
*/ */
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); @Nullable Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
/** /**
* Called whenever an interactive authentication attempt was made, but the credentials * Called whenever an interactive authentication attempt was made, but the credentials

View File

@ -24,6 +24,7 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
@ -50,7 +51,7 @@ public class SimpleUrlAuthenticationFailureHandler implements AuthenticationFail
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private String defaultFailureUrl; private @Nullable String defaultFailureUrl;
private boolean forwardToDestination = false; private boolean forwardToDestination = false;

View File

@ -21,6 +21,7 @@ import java.util.Objects;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import org.jspecify.annotations.Nullable;
/** /**
* A holder of selected HTTP details related to a web authentication request. * A holder of selected HTTP details related to a web authentication request.
@ -34,7 +35,7 @@ public class WebAuthenticationDetails implements Serializable {
private final String remoteAddress; private final String remoteAddress;
private final String sessionId; private final @Nullable String sessionId;
/** /**
* Records the remote address and will also set the session Id if a session already * Records the remote address and will also set the session Id if a session already
@ -51,12 +52,12 @@ public class WebAuthenticationDetails implements Serializable {
* @param sessionId session id * @param sessionId session id
* @since 5.7 * @since 5.7
*/ */
public WebAuthenticationDetails(String remoteAddress, String sessionId) { public WebAuthenticationDetails(String remoteAddress, @Nullable String sessionId) {
this.remoteAddress = remoteAddress; this.remoteAddress = remoteAddress;
this.sessionId = sessionId; this.sessionId = sessionId;
} }
private static String extractSessionId(HttpServletRequest request) { private static @Nullable String extractSessionId(HttpServletRequest request) {
HttpSession session = request.getSession(false); HttpSession session = request.getSession(false);
return (session != null) ? session.getId() : null; return (session != null) ? session.getId() : null;
} }
@ -74,7 +75,7 @@ public class WebAuthenticationDetails implements Serializable {
* from. * from.
* @return the session ID * @return the session ID
*/ */
public String getSessionId() { public @Nullable String getSessionId() {
return this.sessionId; return this.sessionId;
} }

View File

@ -21,6 +21,7 @@ import java.util.List;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -49,7 +50,8 @@ public final class CompositeLogoutHandler implements LogoutHandler {
} }
@Override @Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { public void logout(HttpServletRequest request, HttpServletResponse response,
@Nullable Authentication authentication) {
for (LogoutHandler handler : this.logoutHandlers) { for (LogoutHandler handler : this.logoutHandlers) {
handler.logout(request, response, authentication); handler.logout(request, response, authentication);
} }

View File

@ -23,6 +23,7 @@ import java.util.function.Function;
import jakarta.servlet.http.Cookie; import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -72,7 +73,8 @@ public final class CookieClearingLogoutHandler implements LogoutHandler {
} }
@Override @Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { public void logout(HttpServletRequest request, HttpServletResponse response,
@Nullable Authentication authentication) {
this.cookiesToClear.forEach((f) -> response.addCookie(f.apply(request))); this.cookiesToClear.forEach((f) -> response.addCookie(f.apply(request)));
} }

View File

@ -23,6 +23,7 @@ import java.util.Map;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
@ -39,7 +40,7 @@ public class DelegatingLogoutSuccessHandler implements LogoutSuccessHandler {
private final LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler; private final LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler;
private LogoutSuccessHandler defaultLogoutSuccessHandler; private @Nullable LogoutSuccessHandler defaultLogoutSuccessHandler;
public DelegatingLogoutSuccessHandler(LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler) { public DelegatingLogoutSuccessHandler(LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler) {
Assert.notEmpty(matcherToHandler, "matcherToHandler cannot be null"); Assert.notEmpty(matcherToHandler, "matcherToHandler cannot be null");
@ -47,8 +48,8 @@ public class DelegatingLogoutSuccessHandler implements LogoutSuccessHandler {
} }
@Override @Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
throws IOException, ServletException { @Nullable Authentication authentication) throws IOException, ServletException {
for (Map.Entry<RequestMatcher, LogoutSuccessHandler> entry : this.matcherToHandler.entrySet()) { for (Map.Entry<RequestMatcher, LogoutSuccessHandler> entry : this.matcherToHandler.entrySet()) {
RequestMatcher matcher = entry.getKey(); RequestMatcher matcher = entry.getKey();
if (matcher.matches(request)) { if (matcher.matches(request)) {

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.web.util.UrlUtils; import org.springframework.security.web.util.UrlUtils;
@ -47,8 +48,8 @@ public class ForwardLogoutSuccessHandler implements LogoutSuccessHandler {
} }
@Override @Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
throws IOException, ServletException { @Nullable Authentication authentication) throws IOException, ServletException {
request.getRequestDispatcher(this.targetUrl).forward(request, response); request.getRequestDispatcher(this.targetUrl).forward(request, response);
} }

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.authentication.logout;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.web.header.HeaderWriter; import org.springframework.security.web.header.HeaderWriter;
@ -42,7 +43,8 @@ public final class HeaderWriterLogoutHandler implements LogoutHandler {
} }
@Override @Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { public void logout(HttpServletRequest request, HttpServletResponse response,
@Nullable Authentication authentication) {
this.headerWriter.writeHeaders(request, response); this.headerWriter.writeHeaders(request, response);
} }

View File

@ -20,6 +20,7 @@ import java.io.IOException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -61,8 +62,8 @@ public class HttpStatusReturningLogoutSuccessHandler implements LogoutSuccessHan
* . Sets the status on the {@link HttpServletResponse}. * . Sets the status on the {@link HttpServletResponse}.
*/ */
@Override @Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
throws IOException { @Nullable Authentication authentication) throws IOException {
response.setStatus(this.httpStatusToReturn.value()); response.setStatus(this.httpStatusToReturn.value());
response.getWriter().flush(); response.getWriter().flush();
} }

View File

@ -69,6 +69,7 @@ public class LogoutFilter extends GenericFilterBean {
* intended to perform the actual logout functionality (such as clearing the security * intended to perform the actual logout functionality (such as clearing the security
* context, invalidating the session, etc.). * context, invalidating the session, etc.).
*/ */
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public LogoutFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler... handlers) { public LogoutFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler... handlers) {
this.handler = new CompositeLogoutHandler(handlers); this.handler = new CompositeLogoutHandler(handlers);
Assert.notNull(logoutSuccessHandler, "logoutSuccessHandler cannot be null"); Assert.notNull(logoutSuccessHandler, "logoutSuccessHandler cannot be null");
@ -76,6 +77,7 @@ public class LogoutFilter extends GenericFilterBean {
setFilterProcessesUrl("/logout"); setFilterProcessesUrl("/logout");
} }
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public LogoutFilter(String logoutSuccessUrl, LogoutHandler... handlers) { public LogoutFilter(String logoutSuccessUrl, LogoutHandler... handlers) {
this.handler = new CompositeLogoutHandler(handlers); this.handler = new CompositeLogoutHandler(handlers);
Assert.isTrue(!StringUtils.hasLength(logoutSuccessUrl) || UrlUtils.isValidRedirectUrl(logoutSuccessUrl), Assert.isTrue(!StringUtils.hasLength(logoutSuccessUrl) || UrlUtils.isValidRedirectUrl(logoutSuccessUrl),

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.authentication.logout;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -37,6 +38,6 @@ public interface LogoutHandler {
* @param response the HTTP response * @param response the HTTP response
* @param authentication the current principal details * @param authentication the current principal details
*/ */
void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication); void logout(HttpServletRequest request, HttpServletResponse response, @Nullable Authentication authentication);
} }

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.authentication.logout;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationEventPublisherAware;
@ -32,10 +33,11 @@ import org.springframework.security.core.Authentication;
*/ */
public final class LogoutSuccessEventPublishingLogoutHandler implements LogoutHandler, ApplicationEventPublisherAware { public final class LogoutSuccessEventPublishingLogoutHandler implements LogoutHandler, ApplicationEventPublisherAware {
private ApplicationEventPublisher eventPublisher; private @Nullable ApplicationEventPublisher eventPublisher;
@Override @Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { public void logout(HttpServletRequest request, HttpServletResponse response,
@Nullable Authentication authentication) {
if (this.eventPublisher == null) { if (this.eventPublisher == null) {
return; return;
} }

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -37,7 +38,7 @@ import org.springframework.security.core.Authentication;
*/ */
public interface LogoutSuccessHandler { public interface LogoutSuccessHandler {
void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
throws IOException, ServletException; @Nullable Authentication authentication) throws IOException, ServletException;
} }

View File

@ -21,6 +21,7 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -64,7 +65,8 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
* @param authentication not used (can be <code>null</code>) * @param authentication not used (can be <code>null</code>)
*/ */
@Override @Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { public void logout(HttpServletRequest request, HttpServletResponse response,
@Nullable Authentication authentication) {
Assert.notNull(request, "HttpServletRequest required"); Assert.notNull(request, "HttpServletRequest required");
if (this.invalidateHttpSession) { if (this.invalidateHttpSession) {
HttpSession session = request.getSession(false); HttpSession session = request.getSession(false);

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AbstractAuthenticationTargetUrlRequestHandler; import org.springframework.security.web.authentication.AbstractAuthenticationTargetUrlRequestHandler;
@ -36,8 +37,8 @@ public class SimpleUrlLogoutSuccessHandler extends AbstractAuthenticationTargetU
implements LogoutSuccessHandler { implements LogoutSuccessHandler {
@Override @Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
throws IOException, ServletException { @Nullable Authentication authentication) throws IOException, ServletException {
super.handle(request, response, authentication); super.handle(request, response, authentication);
} }

View File

@ -17,4 +17,7 @@
/** /**
* Logout functionality based around a filter which handles a specific logout URL. * Logout functionality based around a filter which handles a specific logout URL.
*/ */
@NullMarked
package org.springframework.security.web.authentication.logout; package org.springframework.security.web.authentication.logout;
import org.jspecify.annotations.NullMarked;

View File

@ -19,6 +19,7 @@ package org.springframework.security.web.authentication.ott;
import java.time.Duration; import java.time.Duration;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.ott.GenerateOneTimeTokenRequest; import org.springframework.security.authentication.ott.GenerateOneTimeTokenRequest;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -38,7 +39,7 @@ public final class DefaultGenerateOneTimeTokenRequestResolver implements Generat
private Duration expiresIn = DEFAULT_EXPIRES_IN; private Duration expiresIn = DEFAULT_EXPIRES_IN;
@Override @Override
public GenerateOneTimeTokenRequest resolve(HttpServletRequest request) { public @Nullable GenerateOneTimeTokenRequest resolve(HttpServletRequest request) {
String username = request.getParameter("username"); String username = request.getParameter("username");
if (!StringUtils.hasText(username)) { if (!StringUtils.hasText(username)) {
return null; return null;

View File

@ -74,11 +74,11 @@ public final class GenerateOneTimeTokenFilter extends OncePerRequestFilter {
return; return;
} }
GenerateOneTimeTokenRequest generateRequest = this.requestResolver.resolve(request); GenerateOneTimeTokenRequest generateRequest = this.requestResolver.resolve(request);
OneTimeToken ott = this.tokenService.generate(generateRequest);
if (generateRequest == null) { if (generateRequest == null) {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return; return;
} }
OneTimeToken ott = this.tokenService.generate(generateRequest);
this.tokenGenerationSuccessHandler.handle(request, response, ott); this.tokenGenerationSuccessHandler.handle(request, response, ott);
} }

View File

@ -19,6 +19,7 @@ package org.springframework.security.web.authentication.ott;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken; import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -39,7 +40,7 @@ public class OneTimeTokenAuthenticationConverter implements AuthenticationConver
private final Log logger = LogFactory.getLog(getClass()); private final Log logger = LogFactory.getLog(getClass());
@Override @Override
public Authentication convert(HttpServletRequest request) { public @Nullable Authentication convert(HttpServletRequest request) {
String token = request.getParameter("token"); String token = request.getParameter("token");
if (!StringUtils.hasText(token)) { if (!StringUtils.hasText(token)) {
this.logger.debug("No token found in request"); this.logger.debug("No token found in request");

View File

@ -0,0 +1,23 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Package for One Time Token usage.
*/
@NullMarked
package org.springframework.security.web.authentication.ott;
import org.jspecify.annotations.NullMarked;

View File

@ -18,4 +18,7 @@
* Authentication processing mechanisms, which respond to the submission of authentication * Authentication processing mechanisms, which respond to the submission of authentication
* credentials using various protocols (eg BASIC, CAS, form login etc). * credentials using various protocols (eg BASIC, CAS, form login etc).
*/ */
@NullMarked
package org.springframework.security.web.authentication; package org.springframework.security.web.authentication;
import org.jspecify.annotations.NullMarked;

View File

@ -25,6 +25,7 @@ import java.util.Locale;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.password.CompromisedPasswordChecker; import org.springframework.security.authentication.password.CompromisedPasswordChecker;
import org.springframework.security.authentication.password.CompromisedPasswordDecision; import org.springframework.security.authentication.password.CompromisedPasswordDecision;
@ -60,7 +61,7 @@ public final class HaveIBeenPwnedRestApiPasswordChecker implements CompromisedPa
} }
@Override @Override
public CompromisedPasswordDecision check(String password) { public CompromisedPasswordDecision check(@Nullable String password) {
if (password == null) { if (password == null) {
return new CompromisedPasswordDecision(false); return new CompromisedPasswordDecision(false);
} }

View File

@ -0,0 +1,23 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Classes for Password APIs.
*/
@NullMarked
package org.springframework.security.web.authentication.password;
import org.jspecify.annotations.NullMarked;

View File

@ -25,6 +25,7 @@ import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationEventPublisherAware;
@ -96,11 +97,12 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy(); .getContextHolderStrategy();
private ApplicationEventPublisher eventPublisher = null; private @Nullable ApplicationEventPublisher eventPublisher = null;
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource(); private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
private AuthenticationManager authenticationManager = null; @SuppressWarnings("NullAway.Init")
private AuthenticationManager authenticationManager;
private boolean continueFilterChainOnUnsuccessfulAuthentication = true; private boolean continueFilterChainOnUnsuccessfulAuthentication = true;
@ -108,9 +110,9 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
private boolean invalidateSessionOnPrincipalChange = true; private boolean invalidateSessionOnPrincipalChange = true;
private AuthenticationSuccessHandler authenticationSuccessHandler = null; private @Nullable AuthenticationSuccessHandler authenticationSuccessHandler = null;
private AuthenticationFailureHandler authenticationFailureHandler = null; private @Nullable AuthenticationFailureHandler authenticationFailureHandler = null;
private RequestMatcher requiresAuthenticationRequestMatcher = new PreAuthenticatedProcessingRequestMatcher(); private RequestMatcher requiresAuthenticationRequestMatcher = new PreAuthenticatedProcessingRequestMatcher();
@ -357,14 +359,14 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
/** /**
* Override to extract the principal information from the current request * Override to extract the principal information from the current request
*/ */
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request); protected abstract @Nullable Object getPreAuthenticatedPrincipal(HttpServletRequest request);
/** /**
* Override to extract the credentials (if applicable) from the current request. * Override to extract the credentials (if applicable) from the current request.
* Should not return null for a valid principal, though some implementations may * Should not return null for a valid principal, though some implementations may
* return a dummy value. * return a dummy value.
*/ */
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); protected abstract @Nullable Object getPreAuthenticatedCredentials(HttpServletRequest request);
/** /**
* Request matcher for default auth check logic * Request matcher for default auth check logic

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.authentication.preauth;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
@ -51,6 +52,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
private static final Log logger = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class); private static final Log logger = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class);
@SuppressWarnings("NullAway.Init")
private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService; private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
@ -74,7 +76,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
* be ignored to allow other providers to authenticate it. * be ignored to allow other providers to authenticate it.
*/ */
@Override @Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException { public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!supports(authentication.getClass())) { if (!supports(authentication.getClass())) {
return null; return null;
} }

View File

@ -18,6 +18,8 @@ package org.springframework.security.web.authentication.preauth;
import java.util.Collection; import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
@ -34,7 +36,7 @@ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationT
private final Object principal; private final Object principal;
private final Object credentials; private final @Nullable Object credentials;
/** /**
* Constructor used for an authentication request. The * Constructor used for an authentication request. The
@ -43,7 +45,7 @@ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationT
* @param aPrincipal The pre-authenticated principal * @param aPrincipal The pre-authenticated principal
* @param aCredentials The pre-authenticated credentials * @param aCredentials The pre-authenticated credentials
*/ */
public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials) { public PreAuthenticatedAuthenticationToken(Object aPrincipal, @Nullable Object aCredentials) {
super(null); super(null);
this.principal = aPrincipal; this.principal = aPrincipal;
this.credentials = aCredentials; this.credentials = aCredentials;
@ -56,7 +58,7 @@ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationT
* @param aPrincipal The authenticated principal * @param aPrincipal The authenticated principal
* @param anAuthorities The granted authorities * @param anAuthorities The granted authorities
*/ */
public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials, public PreAuthenticatedAuthenticationToken(Object aPrincipal, @Nullable Object aCredentials,
Collection<? extends GrantedAuthority> anAuthorities) { Collection<? extends GrantedAuthority> anAuthorities) {
super(anAuthorities); super(anAuthorities);
this.principal = aPrincipal; this.principal = aPrincipal;
@ -68,7 +70,7 @@ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationT
* Get the credentials * Get the credentials
*/ */
@Override @Override
public Object getCredentials() { public @Nullable Object getCredentials() {
return this.credentials; return this.credentials;
} }

View File

@ -17,6 +17,7 @@
package org.springframework.security.web.authentication.preauth; package org.springframework.security.web.authentication.preauth;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -46,7 +47,7 @@ public class RequestAttributeAuthenticationFilter extends AbstractPreAuthenticat
private String principalEnvironmentVariable = "REMOTE_USER"; private String principalEnvironmentVariable = "REMOTE_USER";
private String credentialsEnvironmentVariable; private @Nullable String credentialsEnvironmentVariable;
private boolean exceptionIfVariableMissing = true; private boolean exceptionIfVariableMissing = true;

View File

@ -17,6 +17,7 @@
package org.springframework.security.web.authentication.preauth; package org.springframework.security.web.authentication.preauth;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -47,7 +48,7 @@ public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedP
private String principalRequestHeader = "SM_USER"; private String principalRequestHeader = "SM_USER";
private String credentialsRequestHeader; private @Nullable String credentialsRequestHeader;
private boolean exceptionIfHeaderMissing = true; private boolean exceptionIfHeaderMissing = true;

View File

@ -52,6 +52,7 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource implements
/** /**
* The role attributes returned by the configured {@code MappableAttributesRetriever} * The role attributes returned by the configured {@code MappableAttributesRetriever}
*/ */
@SuppressWarnings("NullAway.Init")
protected Set<String> j2eeMappableRoles; protected Set<String> j2eeMappableRoles;
protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper(); protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper();

View File

@ -17,6 +17,7 @@
package org.springframework.security.web.authentication.preauth.j2ee; package org.springframework.security.web.authentication.preauth.j2ee;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
@ -35,7 +36,7 @@ public class J2eePreAuthenticatedProcessingFilter extends AbstractPreAuthenticat
* Return the J2EE user name. * Return the J2EE user name.
*/ */
@Override @Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) { protected @Nullable Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
Object principal = (httpRequest.getUserPrincipal() != null) ? httpRequest.getUserPrincipal().getName() : null; Object principal = (httpRequest.getUserPrincipal() != null) ? httpRequest.getUserPrincipal().getName() : null;
this.logger.debug(LogMessage.format("PreAuthenticated J2EE principal: %s", principal)); this.logger.debug(LogMessage.format("PreAuthenticated J2EE principal: %s", principal));
return principal; return principal;

View File

@ -32,6 +32,7 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
@ -60,9 +61,9 @@ public class WebXmlMappableAttributesRetriever
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private ResourceLoader resourceLoader; private @Nullable ResourceLoader resourceLoader;
private Set<String> mappableAttributes; private Set<String> mappableAttributes = new HashSet<>();
@Override @Override
public void setResourceLoader(ResourceLoader resourceLoader) { public void setResourceLoader(ResourceLoader resourceLoader) {
@ -81,6 +82,7 @@ public class WebXmlMappableAttributesRetriever
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
Assert.notNull(this.resourceLoader, "resourceLoader cannot be null");
Resource webXml = this.resourceLoader.getResource("/WEB-INF/web.xml"); Resource webXml = this.resourceLoader.getResource("/WEB-INF/web.xml");
Document doc = getDocument(webXml.getInputStream()); Document doc = getDocument(webXml.getInputStream());
NodeList webApp = doc.getElementsByTagName("web-app"); NodeList webApp = doc.getElementsByTagName("web-app");

View File

@ -21,4 +21,7 @@
* into the security methods exposed by {@code HttpServletRequest} to build * into the security methods exposed by {@code HttpServletRequest} to build
* {@code Authentication} object for the user. * {@code Authentication} object for the user.
*/ */
@NullMarked
package org.springframework.security.web.authentication.preauth.j2ee; package org.springframework.security.web.authentication.preauth.j2ee;
import org.jspecify.annotations.NullMarked;

View File

@ -18,4 +18,7 @@
* Support for "pre-authenticated" scenarios, where Spring Security assumes the incoming * Support for "pre-authenticated" scenarios, where Spring Security assumes the incoming
* request has already been authenticated by some externally configured system. * request has already been authenticated by some externally configured system.
*/ */
@NullMarked
package org.springframework.security.web.authentication.preauth; package org.springframework.security.web.authentication.preauth;
import org.jspecify.annotations.NullMarked;

View File

@ -30,6 +30,7 @@ import javax.security.auth.Subject;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
@ -50,16 +51,16 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
private static final String USER_REGISTRY = "UserRegistry"; private static final String USER_REGISTRY = "UserRegistry";
private static Method getRunAsSubject = null; private static @Nullable Method getRunAsSubject = null;
private static Method getGroupsForUser = null; private static @Nullable Method getGroupsForUser = null;
private static Method getSecurityName = null; private static @Nullable Method getSecurityName = null;
private static Method narrow = null; private static @Nullable Method narrow = null;
// SEC-803 // SEC-803
private static Class<?> wsCredentialClass = null; private static @Nullable Class<?> wsCredentialClass = null;
@Override @Override
public List<String> getGroupsForCurrentUser() { public List<String> getGroupsForCurrentUser() {
@ -67,7 +68,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
} }
@Override @Override
public String getCurrentUserName() { public @Nullable String getCurrentUserName() {
return getSecurityName(getRunAsSubject()); return getSecurityName(getRunAsSubject());
} }
@ -76,7 +77,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
* @param subject The subject for which to retrieve the security name * @param subject The subject for which to retrieve the security name
* @return String the security name for the given subject * @return String the security name for the given subject
*/ */
private static String getSecurityName(final Subject subject) { private static @Nullable String getSecurityName(final Subject subject) {
logger.debug(LogMessage.format("Determining Websphere security name for subject %s", subject)); logger.debug(LogMessage.format("Determining Websphere security name for subject %s", subject));
String userSecurityName = null; String userSecurityName = null;
if (subject != null) { if (subject != null) {
@ -116,7 +117,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
* @return the WebSphere group names for the given security name * @return the WebSphere group names for the given security name
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static List<String> getWebSphereGroups(final String securityName) { private static List<String> getWebSphereGroups(final @Nullable String securityName) {
Context context = null; Context context = null;
try { try {
// TODO: Cache UserRegistry object // TODO: Cache UserRegistry object
@ -140,7 +141,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
} }
} }
private static void closeContext(Context context) { private static void closeContext(@Nullable Context context) {
try { try {
if (context != null) { if (context != null) {
context.close(); context.close();
@ -151,7 +152,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
} }
} }
private static Object invokeMethod(Method method, Object instance, Object... args) { private static Object invokeMethod(Method method, @Nullable Object instance, Object... args) {
try { try {
return method.invoke(instance, args); return method.invoke(instance, args);
} }

View File

@ -18,6 +18,8 @@ package org.springframework.security.web.authentication.preauth.websphere;
import java.util.List; import java.util.List;
import org.jspecify.annotations.Nullable;
/** /**
* Provides indirection between classes using websphere and the actual container * Provides indirection between classes using websphere and the actual container
* interaction, allowing for easier unit testing. * interaction, allowing for easier unit testing.
@ -31,6 +33,6 @@ interface WASUsernameAndGroupsExtractor {
List<String> getGroupsForCurrentUser(); List<String> getGroupsForCurrentUser();
String getCurrentUserName(); @Nullable String getCurrentUserName();
} }

Some files were not shown because too many files have changed in this diff Show More