Browse Source

Add nullability to spring-security-core

Closes gh-17534
pull/17587/head
Rob Winch 6 months ago
parent
commit
7c887d2da1
No known key found for this signature in database
  1. 2
      config/src/test/kotlin/org/springframework/security/config/annotation/web/OAuth2ResourceServerDslTests.kt
  2. 2
      config/src/test/kotlin/org/springframework/security/config/annotation/web/session/SessionConcurrencyDslTests.kt
  3. 2
      config/src/test/kotlin/org/springframework/security/config/web/server/ServerFormLoginDslTests.kt
  4. 2
      config/src/test/kotlin/org/springframework/security/config/web/server/ServerHttpBasicDslTests.kt
  5. 2
      config/src/test/kotlin/org/springframework/security/config/web/server/ServerHttpSecurityDslTests.kt
  6. 2
      config/src/test/kotlin/org/springframework/security/config/web/server/ServerOAuth2ClientDslTests.kt
  7. 4
      core/spring-security-core.gradle
  8. 7
      core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java
  9. 10
      core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java
  10. 3
      core/src/main/java/org/springframework/security/access/annotation/package-info.java
  11. 3
      core/src/main/java/org/springframework/security/access/event/package-info.java
  12. 14
      core/src/main/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandler.java
  13. 7
      core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java
  14. 18
      core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java
  15. 10
      core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java
  16. 23
      core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java
  17. 10
      core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java
  18. 2
      core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java
  19. 6
      core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java
  20. 5
      core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java
  21. 10
      core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionOperations.java
  22. 18
      core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java
  23. 4
      core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java
  24. 6
      core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java
  25. 3
      core/src/main/java/org/springframework/security/access/expression/method/package-info.java
  26. 3
      core/src/main/java/org/springframework/security/access/expression/package-info.java
  27. 2
      core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java
  28. 3
      core/src/main/java/org/springframework/security/access/hierarchicalroles/package-info.java
  29. 13
      core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java
  30. 6
      core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java
  31. 6
      core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java
  32. 7
      core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java
  33. 7
      core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java
  34. 9
      core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java
  35. 5
      core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java
  36. 7
      core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java
  37. 3
      core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java
  38. 2
      core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java
  39. 3
      core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java
  40. 3
      core/src/main/java/org/springframework/security/access/intercept/package-info.java
  41. 6
      core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java
  42. 2
      core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java
  43. 8
      core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java
  44. 13
      core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java
  45. 4
      core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java
  46. 3
      core/src/main/java/org/springframework/security/access/method/package-info.java
  47. 3
      core/src/main/java/org/springframework/security/access/package-info.java
  48. 5
      core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java
  49. 5
      core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java
  50. 11
      core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java
  51. 9
      core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java
  52. 9
      core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java
  53. 3
      core/src/main/java/org/springframework/security/access/prepost/package-info.java
  54. 6
      core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java
  55. 7
      core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java
  56. 3
      core/src/main/java/org/springframework/security/access/vote/package-info.java
  57. 4
      core/src/main/java/org/springframework/security/aot/hint/CoreSecurityRuntimeHints.java
  58. 4
      core/src/main/java/org/springframework/security/aot/hint/OneTimeTokenRuntimeHints.java
  59. 20
      core/src/main/java/org/springframework/security/aot/hint/package-info.java
  60. 12
      core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java
  61. 18
      core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java
  62. 4
      core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java
  63. 13
      core/src/main/java/org/springframework/security/authentication/AuthenticationObservationContext.java
  64. 9
      core/src/main/java/org/springframework/security/authentication/AuthenticationObservationConvention.java
  65. 4
      core/src/main/java/org/springframework/security/authentication/AuthenticationProvider.java
  66. 4
      core/src/main/java/org/springframework/security/authentication/AuthenticationServiceException.java
  67. 10
      core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java
  68. 4
      core/src/main/java/org/springframework/security/authentication/InternalAuthenticationServiceException.java
  69. 1
      core/src/main/java/org/springframework/security/authentication/ObservationAuthenticationManager.java
  70. 5
      core/src/main/java/org/springframework/security/authentication/ProviderManager.java
  71. 4
      core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationProvider.java
  72. 14
      core/src/main/java/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java
  73. 20
      core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
  74. 3
      core/src/main/java/org/springframework/security/authentication/dao/package-info.java
  75. 3
      core/src/main/java/org/springframework/security/authentication/event/package-info.java
  76. 13
      core/src/main/java/org/springframework/security/authentication/jaas/AbstractJaasAuthenticationProvider.java
  77. 1
      core/src/main/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProvider.java
  78. 1
      core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java
  79. 6
      core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java
  80. 2
      core/src/main/java/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java
  81. 5
      core/src/main/java/org/springframework/security/authentication/jaas/JaasPasswordCallbackHandler.java
  82. 11
      core/src/main/java/org/springframework/security/authentication/jaas/SecurityContextLoginModule.java
  83. 3
      core/src/main/java/org/springframework/security/authentication/jaas/event/package-info.java
  84. 8
      core/src/main/java/org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.java
  85. 3
      core/src/main/java/org/springframework/security/authentication/jaas/memory/package-info.java
  86. 3
      core/src/main/java/org/springframework/security/authentication/jaas/package-info.java
  87. 6
      core/src/main/java/org/springframework/security/authentication/ott/InMemoryOneTimeTokenService.java
  88. 11
      core/src/main/java/org/springframework/security/authentication/ott/JdbcOneTimeTokenService.java
  89. 14
      core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationToken.java
  90. 7
      core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenService.java
  91. 20
      core/src/main/java/org/springframework/security/authentication/ott/package-info.java
  92. 20
      core/src/main/java/org/springframework/security/authentication/ott/reactive/package-info.java
  93. 3
      core/src/main/java/org/springframework/security/authentication/package-info.java
  94. 9
      core/src/main/java/org/springframework/security/authentication/password/CompromisedPasswordChecker.java
  95. 7
      core/src/main/java/org/springframework/security/authentication/password/ReactiveCompromisedPasswordChecker.java
  96. 20
      core/src/main/java/org/springframework/security/authentication/password/package-info.java
  97. 8
      core/src/main/java/org/springframework/security/authorization/AuthorizationManager.java
  98. 13
      core/src/main/java/org/springframework/security/authorization/AuthorizationObservationContext.java
  99. 4
      core/src/main/java/org/springframework/security/authorization/AuthorizationProxyFactory.java
  100. 8
      core/src/main/java/org/springframework/security/authorization/ObservationAuthorizationManager.java
  101. Some files were not shown because too many files have changed in this diff Show More

2
config/src/test/kotlin/org/springframework/security/config/annotation/web/OAuth2ResourceServerDslTests.kt

@ -242,7 +242,7 @@ class OAuth2ResourceServerDslTests { @@ -242,7 +242,7 @@ class OAuth2ResourceServerDslTests {
class MockAuthenticationManager(var authentication: Authentication) : AuthenticationManager {
override fun authenticate(authentication: Authentication?): Authentication {
override fun authenticate(authentication: Authentication): Authentication {
return this.authentication
}

2
config/src/test/kotlin/org/springframework/security/config/annotation/web/session/SessionConcurrencyDslTests.kt

@ -217,7 +217,7 @@ class SessionConcurrencyDslTests { @@ -217,7 +217,7 @@ class SessionConcurrencyDslTests {
sessionManagement {
sessionConcurrency {
maximumSessions {
authentication -> if (isAdmin.authorize({ authentication }, null)!!.isGranted) -1 else 1
authentication -> if (isAdmin.authorize({ authentication }, "")!!.isGranted) -1 else 1
}
maxSessionsPreventsLogin = true
}

2
config/src/test/kotlin/org/springframework/security/config/web/server/ServerFormLoginDslTests.kt

@ -172,7 +172,7 @@ class ServerFormLoginDslTests { @@ -172,7 +172,7 @@ class ServerFormLoginDslTests {
}
class NoopReactiveAuthenticationManager: ReactiveAuthenticationManager {
override fun authenticate(authentication: Authentication?): Mono<Authentication> {
override fun authenticate(authentication: Authentication): Mono<Authentication> {
return Mono.empty()
}
}

2
config/src/test/kotlin/org/springframework/security/config/web/server/ServerHttpBasicDslTests.kt

@ -151,7 +151,7 @@ class ServerHttpBasicDslTests { @@ -151,7 +151,7 @@ class ServerHttpBasicDslTests {
}
class NoopReactiveAuthenticationManager: ReactiveAuthenticationManager {
override fun authenticate(authentication: Authentication?): Mono<Authentication> {
override fun authenticate(authentication: Authentication): Mono<Authentication> {
return Mono.empty()
}
}

2
config/src/test/kotlin/org/springframework/security/config/web/server/ServerHttpSecurityDslTests.kt

@ -249,7 +249,7 @@ class ServerHttpSecurityDslTests { @@ -249,7 +249,7 @@ class ServerHttpSecurityDslTests {
}
class NoopReactiveAuthenticationManager: ReactiveAuthenticationManager {
override fun authenticate(authentication: Authentication?): Mono<Authentication> {
override fun authenticate(authentication: Authentication): Mono<Authentication> {
return Mono.empty()
}
}

2
config/src/test/kotlin/org/springframework/security/config/web/server/ServerOAuth2ClientDslTests.kt

@ -276,7 +276,7 @@ class ServerOAuth2ClientDslTests { @@ -276,7 +276,7 @@ class ServerOAuth2ClientDslTests {
}
class NoopReactiveAuthenticationManager: ReactiveAuthenticationManager {
override fun authenticate(authentication: Authentication?): Mono<Authentication> {
override fun authenticate(authentication: Authentication): Mono<Authentication> {
return Mono.empty()
}
}

4
core/spring-security-core.gradle

@ -1,5 +1,9 @@ @@ -1,5 +1,9 @@
import java.util.concurrent.Callable
plugins {
id 'security-nullability'
}
apply plugin: 'io.spring.convention.spring-module'
apply plugin: 'security-kotlin'

7
core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java

@ -25,6 +25,8 @@ import java.util.List; @@ -25,6 +25,8 @@ import java.util.List;
import jakarta.annotation.security.DenyAll;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.access.ConfigAttribute;
@ -39,6 +41,7 @@ import org.springframework.security.access.method.AbstractFallbackMethodSecurity @@ -39,6 +41,7 @@ import org.springframework.security.access.method.AbstractFallbackMethodSecurity
* {@link org.springframework.security.authorization.method.Jsr250AuthorizationManager}
* instead
*/
@NullUnmarked
@Deprecated
public class Jsr250MethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource {
@ -71,11 +74,11 @@ public class Jsr250MethodSecurityMetadataSource extends AbstractFallbackMethodSe @@ -71,11 +74,11 @@ public class Jsr250MethodSecurityMetadataSource extends AbstractFallbackMethodSe
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
public @Nullable Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
private List<ConfigAttribute> processAnnotations(Annotation[] annotations) {
private @Nullable List<ConfigAttribute> processAnnotations(Annotation @Nullable [] annotations) {
if (annotations == null || annotations.length == 0) {
return null;
}

10
core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java

@ -22,6 +22,9 @@ import java.util.ArrayList; @@ -22,6 +22,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.access.ConfigAttribute;
@ -41,13 +44,14 @@ import org.springframework.util.Assert; @@ -41,13 +44,14 @@ import org.springframework.util.Assert;
* @deprecated Use
* {@link org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor#secured}
*/
@NullUnmarked
@Deprecated
@SuppressWarnings({ "unchecked" })
public class SecuredAnnotationSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource {
private AnnotationMetadataExtractor annotationExtractor;
private Class<? extends Annotation> annotationType;
private @Nullable Class<? extends Annotation> annotationType;
public SecuredAnnotationSecurityMetadataSource() {
this(new SecuredAnnotationMetadataExtractor());
@ -73,11 +77,11 @@ public class SecuredAnnotationSecurityMetadataSource extends AbstractFallbackMet @@ -73,11 +77,11 @@ public class SecuredAnnotationSecurityMetadataSource extends AbstractFallbackMet
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
public @Nullable Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
private Collection<ConfigAttribute> processAnnotation(Annotation annotation) {
private @Nullable Collection<ConfigAttribute> processAnnotation(@Nullable Annotation annotation) {
return (annotation != null) ? this.annotationExtractor.extractAttributes(annotation) : null;
}

3
core/src/main/java/org/springframework/security/access/annotation/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Support for JSR-250 and Spring Security {@code @Secured} annotations.
*/
@NullMarked
package org.springframework.security.access.annotation;
import org.jspecify.annotations.NullMarked;

3
core/src/main/java/org/springframework/security/access/event/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Authorization event and listener classes.
*/
@NullMarked
package org.springframework.security.access.event;
import org.jspecify.annotations.NullMarked;

14
core/src/main/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandler.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.access.expression;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryResolver;
@ -43,9 +45,9 @@ public abstract class AbstractSecurityExpressionHandler<T> @@ -43,9 +45,9 @@ public abstract class AbstractSecurityExpressionHandler<T>
private ExpressionParser expressionParser = new SpelExpressionParser();
private BeanResolver beanResolver;
private @Nullable BeanResolver beanResolver;
private RoleHierarchy roleHierarchy;
private @Nullable RoleHierarchy roleHierarchy;
private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
@ -71,7 +73,9 @@ public abstract class AbstractSecurityExpressionHandler<T> @@ -71,7 +73,9 @@ public abstract class AbstractSecurityExpressionHandler<T>
public final EvaluationContext createEvaluationContext(Authentication authentication, T invocation) {
SecurityExpressionOperations root = createSecurityExpressionRoot(authentication, invocation);
StandardEvaluationContext ctx = createEvaluationContextInternal(authentication, invocation);
ctx.setBeanResolver(this.beanResolver);
if (this.beanResolver != null) {
ctx.setBeanResolver(this.beanResolver);
}
ctx.setRootObject(root);
return ctx;
}
@ -101,7 +105,7 @@ public abstract class AbstractSecurityExpressionHandler<T> @@ -101,7 +105,7 @@ public abstract class AbstractSecurityExpressionHandler<T>
protected abstract SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
T invocation);
protected RoleHierarchy getRoleHierarchy() {
protected @Nullable RoleHierarchy getRoleHierarchy() {
return this.roleHierarchy;
}
@ -117,7 +121,7 @@ public abstract class AbstractSecurityExpressionHandler<T> @@ -117,7 +121,7 @@ public abstract class AbstractSecurityExpressionHandler<T>
this.permissionEvaluator = permissionEvaluator;
}
protected BeanResolver getBeanResolver() {
protected @Nullable BeanResolver getBeanResolver() {
return this.beanResolver;
}

7
core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java

@ -27,7 +27,12 @@ public final class ExpressionUtils { @@ -27,7 +27,12 @@ public final class ExpressionUtils {
public static boolean evaluateAsBoolean(Expression expr, EvaluationContext ctx) {
try {
return expr.getValue(ctx, Boolean.class);
Boolean result = expr.getValue(ctx, Boolean.class);
if (result == null) {
throw new IllegalArgumentException(
"Expression was null but expected boolean result '" + expr.getExpressionString() + "'");
}
return result;
}
catch (EvaluationException ex) {
throw new IllegalArgumentException("Failed to evaluate expression '" + expr.getExpressionString() + "'",

18
core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java

@ -21,9 +21,12 @@ import java.util.Collection; @@ -21,9 +21,12 @@ import java.util.Collection;
import java.util.Set;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
@ -41,11 +44,11 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat @@ -41,11 +44,11 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
private final Supplier<Authentication> authentication;
private AuthenticationTrustResolver trustResolver;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
private RoleHierarchy roleHierarchy;
private @Nullable RoleHierarchy roleHierarchy;
private Set<String> roles;
private @Nullable Set<String> roles;
private String defaultRolePrefix = "ROLE_";
@ -59,7 +62,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat @@ -59,7 +62,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
*/
public final boolean denyAll = false;
private PermissionEvaluator permissionEvaluator;
private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
public final String read = "read";
@ -114,7 +117,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat @@ -114,7 +117,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
return hasAnyAuthorityName(this.defaultRolePrefix, roles);
}
private boolean hasAnyAuthorityName(String prefix, String... roles) {
private boolean hasAnyAuthorityName(@Nullable String prefix, String... roles) {
Set<String> roleSet = getAuthoritySet();
for (String role : roles) {
String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
@ -166,7 +169,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat @@ -166,7 +169,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
* {@link #getAuthentication()}
* @return
*/
public Object getPrincipal() {
public @Nullable Object getPrincipal() {
return getAuthentication().getPrincipal();
}
@ -218,6 +221,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat @@ -218,6 +221,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
}
public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
Assert.notNull(permissionEvaluator, "permissionEvaluator cannot be null");
this.permissionEvaluator = permissionEvaluator;
}
@ -228,7 +232,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat @@ -228,7 +232,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
* @param role
* @return
*/
private static String getRoleWithDefaultPrefix(String defaultRolePrefix, String role) {
private static String getRoleWithDefaultPrefix(@Nullable String defaultRolePrefix, String role) {
if (role == null) {
return role;
}

10
core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
package org.springframework.security.access.expression.method;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@ -35,12 +38,13 @@ import org.springframework.util.Assert; @@ -35,12 +38,13 @@ import org.springframework.util.Assert;
* @deprecated Use {@link org.springframework.security.authorization.AuthorizationManager}
* interceptors instead
*/
@NullUnmarked
@Deprecated
abstract class AbstractExpressionBasedMethodConfigAttribute implements ConfigAttribute {
private final Expression filterExpression;
private final @Nullable Expression filterExpression;
private final Expression authorizeExpression;
private final @Nullable Expression authorizeExpression;
/**
* Parses the supplied expressions as Spring-EL.
@ -71,7 +75,7 @@ abstract class AbstractExpressionBasedMethodConfigAttribute implements ConfigAtt @@ -71,7 +75,7 @@ abstract class AbstractExpressionBasedMethodConfigAttribute implements ConfigAtt
}
@Override
public String getAttribute() {
public @Nullable String getAttribute() {
return null;
}

23
core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java

@ -23,17 +23,20 @@ import java.util.Collection; @@ -23,17 +23,20 @@ import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.log.LogMessage;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.access.PermissionCacheOptimizer;
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
@ -64,7 +67,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr @@ -64,7 +67,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultSecurityParameterNameDiscoverer();
private PermissionCacheOptimizer permissionCacheOptimizer = null;
private @Nullable PermissionCacheOptimizer permissionCacheOptimizer = null;
private String defaultRolePrefix = "ROLE_";
@ -85,7 +88,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr @@ -85,7 +88,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(root, mi,
getParameterNameDiscoverer());
ctx.setBeanResolver(getBeanResolver());
Optional.ofNullable(getBeanResolver()).ifPresent(ctx::setBeanResolver);
return ctx;
}
@ -104,7 +107,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr @@ -104,7 +107,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
root.setThis(invocation.getThis());
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(getTrustResolver());
root.setRoleHierarchy(getRoleHierarchy());
Optional.ofNullable(getRoleHierarchy()).ifPresent(root::setRoleHierarchy);
root.setDefaultRolePrefix(getDefaultRolePrefix());
return root;
}
@ -119,14 +122,15 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr @@ -119,14 +122,15 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
* {@link Stream}
*/
@Override
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
public Object filter(@Nullable Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx.getRootObject()
.getValue();
Assert.notNull(rootObject, "rootObject cannot be null");
this.logger.debug(LogMessage.format("Filtering with expression: %s", filterExpression.getExpressionString()));
if (filterTarget instanceof Collection) {
return filterCollection((Collection<?>) filterTarget, filterExpression, ctx, rootObject);
}
if (filterTarget.getClass().isArray()) {
if (filterTarget != null && filterTarget.getClass().isArray()) {
return filterArray((Object[]) filterTarget, filterExpression, ctx, rootObject);
}
if (filterTarget instanceof Map) {
@ -259,8 +263,13 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr @@ -259,8 +263,13 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
}
@Override
public void setReturnObject(Object returnObject, EvaluationContext ctx) {
((MethodSecurityExpressionOperations) ctx.getRootObject().getValue()).setReturnObject(returnObject);
public void setReturnObject(@Nullable Object returnObject, EvaluationContext ctx) {
TypedValue rootObject = ctx.getRootObject();
Assert.notNull(rootObject, "rootObject cannot be null");
MethodSecurityExpressionOperations methodOperations = (MethodSecurityExpressionOperations) rootObject
.getValue();
Assert.notNull(methodOperations, "MethodSecurityExpressionOperations cannot be null");
methodOperations.setReturnObject(returnObject);
}
/**

10
core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java

@ -16,12 +16,16 @@ @@ -16,12 +16,16 @@
package org.springframework.security.access.expression.method;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParseException;
import org.springframework.security.access.prepost.PostInvocationAttribute;
import org.springframework.security.access.prepost.PreInvocationAttribute;
import org.springframework.security.access.prepost.PrePostInvocationAttributeFactory;
import org.springframework.util.Assert;
/**
* {@link PrePostInvocationAttributeFactory} which interprets the annotation value as an
@ -33,16 +37,18 @@ import org.springframework.security.access.prepost.PrePostInvocationAttributeFac @@ -33,16 +37,18 @@ import org.springframework.security.access.prepost.PrePostInvocationAttributeFac
* @deprecated Use {@link org.springframework.security.authorization.AuthorizationManager}
* interceptors instead
*/
@NullUnmarked
@Deprecated
public class ExpressionBasedAnnotationAttributeFactory implements PrePostInvocationAttributeFactory {
private final Object parserLock = new Object();
private ExpressionParser parser;
private @Nullable ExpressionParser parser;
private MethodSecurityExpressionHandler handler;
public ExpressionBasedAnnotationAttributeFactory(MethodSecurityExpressionHandler handler) {
Assert.notNull(handler, "handler cannot be null");
this.handler = handler;
}
@ -64,7 +70,7 @@ public class ExpressionBasedAnnotationAttributeFactory implements PrePostInvocat @@ -64,7 +70,7 @@ public class ExpressionBasedAnnotationAttributeFactory implements PrePostInvocat
}
@Override
public PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute,
public @Nullable PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute,
String postAuthorizeAttribute) {
try {
ExpressionParser parser = getParser();

2
core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java

@ -19,6 +19,7 @@ package org.springframework.security.access.expression.method; @@ -19,6 +19,7 @@ package org.springframework.security.access.expression.method;
import java.util.Collection;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
@ -37,6 +38,7 @@ import org.springframework.util.Assert; @@ -37,6 +38,7 @@ import org.springframework.util.Assert;
* {@link org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor}
* instead
*/
@NullUnmarked
@Deprecated
public class ExpressionBasedPreInvocationAdvice implements PreInvocationAuthorizationAdvice {

6
core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java

@ -19,6 +19,7 @@ package org.springframework.security.access.expression.method; @@ -19,6 +19,7 @@ package org.springframework.security.access.expression.method;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
@ -48,6 +49,8 @@ class MethodSecurityEvaluationContext extends MethodBasedEvaluationContext { @@ -48,6 +49,8 @@ class MethodSecurityEvaluationContext extends MethodBasedEvaluationContext {
this(user, mi, new DefaultSecurityParameterNameDiscoverer());
}
@NullUnmarked // FIXME: rootObject in MethodBasedEvaluationContext is non-null
// (probably needs changed) but StandardEvaluationContext is Nullable
MethodSecurityEvaluationContext(Authentication user, MethodInvocation mi,
ParameterNameDiscoverer parameterNameDiscoverer) {
super(mi.getThis(), getSpecificMethod(mi), mi.getArguments(), parameterNameDiscoverer);
@ -59,7 +62,8 @@ class MethodSecurityEvaluationContext extends MethodBasedEvaluationContext { @@ -59,7 +62,8 @@ class MethodSecurityEvaluationContext extends MethodBasedEvaluationContext {
}
private static Method getSpecificMethod(MethodInvocation mi) {
return AopUtils.getMostSpecificMethod(mi.getMethod(), AopProxyUtils.ultimateTargetClass(mi.getThis()));
Class<?> targetClass = (mi.getThis() != null) ? AopProxyUtils.ultimateTargetClass(mi.getThis()) : null;
return AopUtils.getMostSpecificMethod(mi.getMethod(), targetClass);
}
}

5
core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.security.access.expression.method;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
@ -41,7 +42,7 @@ public interface MethodSecurityExpressionHandler extends SecurityExpressionHandl @@ -41,7 +42,7 @@ public interface MethodSecurityExpressionHandler extends SecurityExpressionHandl
* {@link #createEvaluationContext(org.springframework.security.core.Authentication, Object)}
* @return the filtered collection or array
*/
Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx);
Object filter(@Nullable Object filterTarget, Expression filterExpression, EvaluationContext ctx);
/**
* Used to inform the expression system of the return object for the given evaluation
@ -51,6 +52,6 @@ public interface MethodSecurityExpressionHandler extends SecurityExpressionHandl @@ -51,6 +52,6 @@ public interface MethodSecurityExpressionHandler extends SecurityExpressionHandl
* call to
* {@link #createEvaluationContext(org.springframework.security.core.Authentication, Object)}
*/
void setReturnObject(Object returnObject, EvaluationContext ctx);
void setReturnObject(@Nullable Object returnObject, EvaluationContext ctx);
}

10
core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionOperations.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.access.expression.method;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.expression.SecurityExpressionOperations;
/**
@ -29,12 +31,12 @@ public interface MethodSecurityExpressionOperations extends SecurityExpressionOp @@ -29,12 +31,12 @@ public interface MethodSecurityExpressionOperations extends SecurityExpressionOp
void setFilterObject(Object filterObject);
Object getFilterObject();
@Nullable Object getFilterObject();
void setReturnObject(Object returnObject);
void setReturnObject(@Nullable Object returnObject);
Object getReturnObject();
@Nullable Object getReturnObject();
Object getThis();
@Nullable Object getThis();
}

18
core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java

@ -18,6 +18,8 @@ package org.springframework.security.access.expression.method; @@ -18,6 +18,8 @@ package org.springframework.security.access.expression.method;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.core.Authentication;
@ -30,11 +32,11 @@ import org.springframework.security.core.Authentication; @@ -30,11 +32,11 @@ import org.springframework.security.core.Authentication;
*/
class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
private Object filterObject;
private @Nullable Object filterObject;
private Object returnObject;
private @Nullable Object returnObject;
private Object target;
private @Nullable Object target;
MethodSecurityExpressionRoot(Authentication a) {
super(a);
@ -50,17 +52,17 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements Met @@ -50,17 +52,17 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements Met
}
@Override
public Object getFilterObject() {
public @Nullable Object getFilterObject() {
return this.filterObject;
}
@Override
public void setReturnObject(Object returnObject) {
public void setReturnObject(@Nullable Object returnObject) {
this.returnObject = returnObject;
}
@Override
public Object getReturnObject() {
public @Nullable Object getReturnObject() {
return this.returnObject;
}
@ -70,12 +72,12 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements Met @@ -70,12 +72,12 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements Met
* protected.
* @param target the target object on which the method in is being invoked.
*/
void setThis(Object target) {
void setThis(@Nullable Object target) {
this.target = target;
}
@Override
public Object getThis() {
public @Nullable Object getThis() {
return this.target;
}

4
core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.access.expression.method;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.security.access.prepost.PostInvocationAttribute;
@ -36,7 +38,7 @@ class PostInvocationExpressionAttribute extends AbstractExpressionBasedMethodCon @@ -36,7 +38,7 @@ class PostInvocationExpressionAttribute extends AbstractExpressionBasedMethodCon
super(filterExpression, authorizeExpression);
}
PostInvocationExpressionAttribute(Expression filterExpression, Expression authorizeExpression)
PostInvocationExpressionAttribute(@Nullable Expression filterExpression, @Nullable Expression authorizeExpression)
throws ParseException {
super(filterExpression, authorizeExpression);
}

6
core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.access.expression.method;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.security.access.prepost.PreInvocationAttribute;
@ -40,8 +42,8 @@ class PreInvocationExpressionAttribute extends AbstractExpressionBasedMethodConf @@ -40,8 +42,8 @@ class PreInvocationExpressionAttribute extends AbstractExpressionBasedMethodConf
this.filterTarget = filterTarget;
}
PreInvocationExpressionAttribute(Expression filterExpression, String filterTarget, Expression authorizeExpression)
throws ParseException {
PreInvocationExpressionAttribute(@Nullable Expression filterExpression, String filterTarget,
Expression authorizeExpression) throws ParseException {
super(filterExpression, authorizeExpression);
this.filterTarget = filterTarget;
}

3
core/src/main/java/org/springframework/security/access/expression/method/package-info.java

@ -19,4 +19,7 @@ @@ -19,4 +19,7 @@
*
* @since 3.0
*/
@NullMarked
package org.springframework.security.access.expression.method;
import org.jspecify.annotations.NullMarked;

3
core/src/main/java/org/springframework/security/access/expression/package-info.java

@ -22,4 +22,7 @@ @@ -22,4 +22,7 @@
*
* @since 3.0
*/
@NullMarked
package org.springframework.security.access.expression;
import org.jspecify.annotations.NullMarked;

2
core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java

@ -86,7 +86,7 @@ public final class RoleHierarchyImpl implements RoleHierarchy { @@ -86,7 +86,7 @@ public final class RoleHierarchyImpl implements RoleHierarchy {
* {@code rolesReachableInOneOrMoreStepsMap} is a Map that under the key of a specific
* role name contains a set of all roles reachable from this role in 1 or more steps
*/
private Map<String, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap = null;
private final Map<String, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap;
private RoleHierarchyImpl(Map<String, Set<GrantedAuthority>> hierarchy) {
this.rolesReachableInOneOrMoreStepsMap = buildRolesReachableInOneOrMoreStepsMap(hierarchy);

3
core/src/main/java/org/springframework/security/access/hierarchicalroles/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Role hierarchy implementation.
*/
@NullMarked
package org.springframework.security.access.hierarchicalroles;
import org.jspecify.annotations.NullMarked;

13
core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java

@ -22,6 +22,8 @@ import java.util.Set; @@ -22,6 +22,8 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEvent;
@ -114,6 +116,7 @@ import org.springframework.util.CollectionUtils; @@ -114,6 +116,7 @@ import org.springframework.util.CollectionUtils;
* {@link org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor}
* for method security.
*/
@NullUnmarked
@Deprecated
public abstract class AbstractSecurityInterceptor
implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware {
@ -125,11 +128,11 @@ public abstract class AbstractSecurityInterceptor @@ -125,11 +128,11 @@ public abstract class AbstractSecurityInterceptor
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private ApplicationEventPublisher eventPublisher;
private @Nullable ApplicationEventPublisher eventPublisher;
private AccessDecisionManager accessDecisionManager;
private @Nullable AccessDecisionManager accessDecisionManager;
private AfterInvocationManager afterInvocationManager;
private @Nullable AfterInvocationManager afterInvocationManager;
private AuthenticationManager authenticationManager = new NoOpAuthenticationManager();
@ -190,7 +193,7 @@ public abstract class AbstractSecurityInterceptor @@ -190,7 +193,7 @@ public abstract class AbstractSecurityInterceptor
}
}
protected InterceptorStatusToken beforeInvocation(Object object) {
protected @Nullable InterceptorStatusToken beforeInvocation(Object object) {
Assert.notNull(object, "Object was null");
if (!getSecureObjectClass().isAssignableFrom(object.getClass())) {
throw new IllegalArgumentException("Security invocation attempted for object " + object.getClass().getName()
@ -291,7 +294,7 @@ public abstract class AbstractSecurityInterceptor @@ -291,7 +294,7 @@ public abstract class AbstractSecurityInterceptor
* @return the object the secure object invocation should ultimately return to its
* caller (may be <tt>null</tt>)
*/
protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) {
protected Object afterInvocation(InterceptorStatusToken token, @Nullable Object returnedObject) {
if (token == null) {
// public object
return returnedObject;

6
core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java

@ -22,6 +22,8 @@ import java.util.List; @@ -22,6 +22,8 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.log.LogMessage;
@ -52,12 +54,14 @@ import org.springframework.util.CollectionUtils; @@ -52,12 +54,14 @@ import org.springframework.util.CollectionUtils;
* @see org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor
* @deprecated Use delegation with {@link AuthorizationManager}
*/
@NullUnmarked
@Deprecated
public class AfterInvocationProviderManager implements AfterInvocationManager, InitializingBean {
protected static final Log logger = LogFactory.getLog(AfterInvocationProviderManager.class);
private List<AfterInvocationProvider> providers;
@SuppressWarnings("NullAway.Init")
private @Nullable List<AfterInvocationProvider> providers;
@Override
public void afterPropertiesSet() {

6
core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java

@ -21,6 +21,8 @@ import java.util.Collection; @@ -21,6 +21,8 @@ import java.util.Collection;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.log.LogMessage;
@ -46,12 +48,14 @@ import org.springframework.util.Assert; @@ -46,12 +48,14 @@ import org.springframework.util.Assert;
* @deprecated Use {@link org.springframework.security.authorization.AuthorizationManager}
* instead
*/
@NullUnmarked
@Deprecated
public class MethodInvocationPrivilegeEvaluator implements InitializingBean {
protected static final Log logger = LogFactory.getLog(MethodInvocationPrivilegeEvaluator.class);
private AbstractSecurityInterceptor securityInterceptor;
@SuppressWarnings("NullAway.Init")
private @Nullable AbstractSecurityInterceptor securityInterceptor;
@Override
public void afterPropertiesSet() {

7
core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java

@ -18,6 +18,9 @@ package org.springframework.security.access.intercept; @@ -18,6 +18,9 @@ package org.springframework.security.access.intercept;
import java.util.Collection;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
@ -30,11 +33,13 @@ import org.springframework.security.core.Authentication; @@ -30,11 +33,13 @@ import org.springframework.security.core.Authentication;
* @author Ben Alex
* @deprecated please see {@link RunAsManager} deprecation notice
*/
@NullUnmarked
@Deprecated
final class NullRunAsManager implements RunAsManager {
@Override
public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> config) {
public @Nullable Authentication buildRunAs(Authentication authentication, Object object,
Collection<ConfigAttribute> config) {
return null;
}

7
core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
package org.springframework.security.access.intercept;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
@ -44,12 +47,14 @@ import org.springframework.util.Assert; @@ -44,12 +47,14 @@ import org.springframework.util.Assert;
* class is only used by now-deprecated components. There is not yet an equivalent
* replacement in Spring Security.
*/
@NullUnmarked
@Deprecated
public class RunAsImplAuthenticationProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware {
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private String key;
@SuppressWarnings("NullAway.Init")
private @Nullable String key;
@Override
public void afterPropertiesSet() {

9
core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java

@ -20,6 +20,9 @@ import java.util.ArrayList; @@ -20,6 +20,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
@ -56,10 +59,12 @@ import org.springframework.util.Assert; @@ -56,10 +59,12 @@ import org.springframework.util.Assert;
* class is only used by now-deprecated components. There is not yet an equivalent
* replacement in Spring Security.
*/
@NullUnmarked
@Deprecated
public class RunAsManagerImpl implements RunAsManager, InitializingBean {
private String key;
@SuppressWarnings("NullAway.Init")
private @Nullable String key;
private String rolePrefix = "ROLE_";
@ -70,7 +75,7 @@ public class RunAsManagerImpl implements RunAsManager, InitializingBean { @@ -70,7 +75,7 @@ public class RunAsManagerImpl implements RunAsManager, InitializingBean {
}
@Override
public Authentication buildRunAs(Authentication authentication, Object object,
public @Nullable Authentication buildRunAs(Authentication authentication, Object object,
Collection<ConfigAttribute> attributes) {
List<GrantedAuthority> newAuthorities = new ArrayList<>();
for (ConfigAttribute attribute : attributes) {

5
core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java

@ -18,6 +18,8 @@ package org.springframework.security.access.intercept.aopalliance; @@ -18,6 +18,8 @@ package org.springframework.security.access.intercept.aopalliance;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
@ -42,10 +44,11 @@ import org.springframework.security.access.method.MethodSecurityMetadataSource; @@ -42,10 +44,11 @@ import org.springframework.security.access.method.MethodSecurityMetadataSource;
* {@link org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor}
* instead
*/
@NullUnmarked
@Deprecated
public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor {
private MethodSecurityMetadataSource securityMetadataSource;
private @Nullable MethodSecurityMetadataSource securityMetadataSource;
@Override
public Class<?> getSecureObjectClass() {

7
core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java

@ -23,6 +23,8 @@ import java.lang.reflect.Method; @@ -23,6 +23,8 @@ import java.lang.reflect.Method;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
@ -53,17 +55,18 @@ import org.springframework.util.CollectionUtils; @@ -53,17 +55,18 @@ import org.springframework.util.CollectionUtils;
* @author Luke Taylor
* @deprecated Use {@link EnableMethodSecurity} or publish interceptors directly
*/
@NullUnmarked
@Deprecated
@SuppressWarnings("serial")
public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
private transient MethodSecurityMetadataSource attributeSource;
private transient MethodInterceptor interceptor;
private transient @Nullable MethodInterceptor interceptor;
private final Pointcut pointcut = new MethodSecurityMetadataSourcePointcut();
private BeanFactory beanFactory;
private @Nullable BeanFactory beanFactory;
private final String adviceBeanName;

3
core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* Enforces security for AOP Alliance <code>MethodInvocation</code>s, such as via Spring
* AOP.
*/
@NullMarked
package org.springframework.security.access.intercept.aopalliance;
import org.jspecify.annotations.NullMarked;

2
core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java

@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation; @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.CodeSignature;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.util.Assert;
@ -35,6 +36,7 @@ import org.springframework.util.Assert; @@ -35,6 +36,7 @@ import org.springframework.util.Assert;
* @deprecated This class will be removed from the public API. See
* `JoinPointMethodInvocation` in `spring-security-aspects` for its replacement
*/
@NullUnmarked
@Deprecated
public final class MethodInvocationAdapter implements MethodInvocation {

3
core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* Enforces security for AspectJ <code>JointPoint</code>s, delegating secure object
* callbacks to the calling aspect.
*/
@NullMarked
package org.springframework.security.access.intercept.aspectj;
import org.jspecify.annotations.NullMarked;

3
core/src/main/java/org/springframework/security/access/intercept/package-info.java

@ -33,4 +33,7 @@ @@ -33,4 +33,7 @@
* an appropriate {@link org.springframework.security.access.SecurityMetadataSource} for
* the type of resources the secure object represents.
*/
@NullMarked
package org.springframework.security.access.intercept;
import org.jspecify.annotations.NullMarked;

6
core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java

@ -20,6 +20,8 @@ import java.lang.reflect.Method; @@ -20,6 +20,8 @@ import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.support.AopUtils;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authorization.AuthorizationManager;
@ -52,7 +54,7 @@ import org.springframework.security.authorization.AuthorizationManager; @@ -52,7 +54,7 @@ import org.springframework.security.authorization.AuthorizationManager;
public abstract class AbstractFallbackMethodSecurityMetadataSource extends AbstractMethodSecurityMetadataSource {
@Override
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
public Collection<ConfigAttribute> getAttributes(Method method, @Nullable Class<?> targetClass) {
// The method may be on an interface, but we need attributes from the target
// class.
// If the target class is null, the method will be unchanged.
@ -92,7 +94,7 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends Abstr @@ -92,7 +94,7 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends Abstr
* @param targetClass the target class for the invocation (may be <code>null</code>)
* @return the security metadata (or null if no metadata applies)
*/
protected abstract Collection<ConfigAttribute> findAttributes(Method method, Class<?> targetClass);
protected abstract Collection<ConfigAttribute> findAttributes(Method method, @Nullable Class<?> targetClass);
/**
* Obtains the security metadata registered against the specified class.

2
core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java

@ -21,6 +21,7 @@ import java.util.Collection; @@ -21,6 +21,7 @@ import java.util.Collection;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.security.access.ConfigAttribute;
@ -36,6 +37,7 @@ import org.springframework.security.authorization.AuthorizationManager; @@ -36,6 +37,7 @@ import org.springframework.security.authorization.AuthorizationManager;
* {@code <method-security>} and {@code <intercept-methods>} instead or use
* annotation-based or {@link AuthorizationManager}-based authorization
*/
@NullUnmarked
@Deprecated
public abstract class AbstractMethodSecurityMetadataSource implements MethodSecurityMetadataSource {

8
core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java

@ -25,6 +25,8 @@ import java.util.List; @@ -25,6 +25,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authorization.AuthorizationManager;
@ -57,7 +59,7 @@ public final class DelegatingMethodSecurityMetadataSource extends AbstractMethod @@ -57,7 +59,7 @@ public final class DelegatingMethodSecurityMetadataSource extends AbstractMethod
}
@Override
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
public Collection<ConfigAttribute> getAttributes(Method method, @Nullable Class<?> targetClass) {
DefaultCacheKey cacheKey = new DefaultCacheKey(method, targetClass);
synchronized (this.attributeCache) {
Collection<ConfigAttribute> cached = this.attributeCache.get(cacheKey);
@ -104,9 +106,9 @@ public final class DelegatingMethodSecurityMetadataSource extends AbstractMethod @@ -104,9 +106,9 @@ public final class DelegatingMethodSecurityMetadataSource extends AbstractMethod
private final Method method;
private final Class<?> targetClass;
private final @Nullable Class<?> targetClass;
DefaultCacheKey(Method method, Class<?> targetClass) {
DefaultCacheKey(Method method, @Nullable Class<?> targetClass) {
this.method = method;
this.targetClass = targetClass;
}

13
core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java

@ -25,6 +25,9 @@ import java.util.List; @@ -25,6 +25,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.core.log.LogMessage;
import org.springframework.security.access.ConfigAttribute;
@ -47,11 +50,13 @@ import org.springframework.util.ClassUtils; @@ -47,11 +50,13 @@ import org.springframework.util.ClassUtils;
* {@code <method-security>} and {@code <intercept-methods>} instead or use
* annotation-based or {@link AuthorizationManager}-based authorization
*/
@NullUnmarked
@Deprecated
public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource
implements BeanClassLoaderAware {
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
@SuppressWarnings("NullAway")
private @Nullable ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/**
* Map from RegisteredMethod to ConfigAttribute list
@ -80,7 +85,7 @@ public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethod @@ -80,7 +85,7 @@ public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethod
* Implementation does not support class-level attributes.
*/
@Override
protected Collection<ConfigAttribute> findAttributes(Class<?> clazz) {
protected @Nullable Collection<ConfigAttribute> findAttributes(Class<?> clazz) {
return null;
}
@ -89,14 +94,14 @@ public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethod @@ -89,14 +94,14 @@ public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethod
* applicable.
*/
@Override
protected Collection<ConfigAttribute> findAttributes(Method method, Class<?> targetClass) {
protected @Nullable Collection<ConfigAttribute> findAttributes(Method method, Class<?> targetClass) {
if (targetClass == null) {
return null;
}
return findAttributesSpecifiedAgainst(method, targetClass);
}
private List<ConfigAttribute> findAttributesSpecifiedAgainst(Method method, Class<?> clazz) {
private @Nullable List<ConfigAttribute> findAttributesSpecifiedAgainst(Method method, Class<?> clazz) {
RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz);
if (this.methodMap.containsKey(registeredMethod)) {
return this.methodMap.get(registeredMethod);

4
core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java

@ -19,6 +19,8 @@ package org.springframework.security.access.method; @@ -19,6 +19,8 @@ package org.springframework.security.access.method;
import java.lang.reflect.Method;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.authorization.AuthorizationManager;
@ -37,6 +39,6 @@ import org.springframework.security.authorization.AuthorizationManager; @@ -37,6 +39,6 @@ import org.springframework.security.authorization.AuthorizationManager;
@Deprecated
public interface MethodSecurityMetadataSource extends SecurityMetadataSource {
Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass);
Collection<ConfigAttribute> getAttributes(Method method, @Nullable Class<?> targetClass);
}

3
core/src/main/java/org/springframework/security/access/method/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* Provides {@code SecurityMetadataSource} implementations for securing Java method
* invocations via different AOP libraries.
*/
@NullMarked
package org.springframework.security.access.method;
import org.jspecify.annotations.NullMarked;

3
core/src/main/java/org/springframework/security/access/package-info.java

@ -21,4 +21,7 @@ @@ -21,4 +21,7 @@
* {@link org.springframework.security.access.AccessDecisionManager AccessDecisionManager}
* interface.
*/
@NullMarked
package org.springframework.security.access;
import org.jspecify.annotations.NullMarked;

5
core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java

@ -21,6 +21,8 @@ import java.util.Collection; @@ -21,6 +21,8 @@ import java.util.Collection;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.AfterInvocationProvider;
@ -40,6 +42,7 @@ import org.springframework.security.core.Authentication; @@ -40,6 +42,7 @@ import org.springframework.security.core.Authentication;
* {@link org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor}
* instead
*/
@NullUnmarked
@Deprecated
public class PostInvocationAdviceProvider implements AfterInvocationProvider {
@ -62,7 +65,7 @@ public class PostInvocationAdviceProvider implements AfterInvocationProvider { @@ -62,7 +65,7 @@ public class PostInvocationAdviceProvider implements AfterInvocationProvider {
returnedObject);
}
private PostInvocationAttribute findPostInvocationAttribute(Collection<ConfigAttribute> config) {
private @Nullable PostInvocationAttribute findPostInvocationAttribute(Collection<ConfigAttribute> config) {
for (ConfigAttribute attribute : config) {
if (attribute instanceof PostInvocationAttribute) {
return (PostInvocationAttribute) attribute;

5
core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java

@ -21,6 +21,8 @@ import java.util.Collection; @@ -21,6 +21,8 @@ import java.util.Collection;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
@ -42,6 +44,7 @@ import org.springframework.security.core.Authentication; @@ -42,6 +44,7 @@ import org.springframework.security.core.Authentication;
* {@link org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor}
* instead
*/
@NullUnmarked
@Deprecated
public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVoter<MethodInvocation> {
@ -75,7 +78,7 @@ public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVote @@ -75,7 +78,7 @@ public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVote
return this.preAdvice.before(authentication, method, preAttr) ? ACCESS_GRANTED : ACCESS_DENIED;
}
private PreInvocationAttribute findPreInvocationAttribute(Collection<ConfigAttribute> config) {
private @Nullable PreInvocationAttribute findPreInvocationAttribute(Collection<ConfigAttribute> config) {
for (ConfigAttribute attribute : config) {
if (attribute instanceof PreInvocationAttribute) {
return (PreInvocationAttribute) attribute;

11
core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java

@ -22,6 +22,8 @@ import java.util.Collection; @@ -22,6 +22,8 @@ import java.util.Collection;
import kotlinx.coroutines.reactive.ReactiveFlowKt;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
@ -54,6 +56,7 @@ import org.springframework.util.Assert; @@ -54,6 +56,7 @@ import org.springframework.util.Assert;
* or
* {@link org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor}
*/
@NullUnmarked
@Deprecated
public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor {
@ -142,7 +145,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor @@ -142,7 +145,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor
.map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
}
private static <T extends Publisher<?>> T proceed(final MethodInvocation invocation) {
private static <T extends Publisher<?>> @Nullable T proceed(final MethodInvocation invocation) {
try {
return (T) invocation.proceed();
}
@ -151,7 +154,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor @@ -151,7 +154,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor
}
}
private static Object flowProceed(final MethodInvocation invocation) {
private static @Nullable Object flowProceed(final MethodInvocation invocation) {
try {
return invocation.proceed();
}
@ -160,7 +163,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor @@ -160,7 +163,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor
}
}
private static PostInvocationAttribute findPostInvocationAttribute(Collection<ConfigAttribute> config) {
private static @Nullable PostInvocationAttribute findPostInvocationAttribute(Collection<ConfigAttribute> config) {
for (ConfigAttribute attribute : config) {
if (attribute instanceof PostInvocationAttribute) {
return (PostInvocationAttribute) attribute;
@ -169,7 +172,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor @@ -169,7 +172,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor
return null;
}
private static PreInvocationAttribute findPreInvocationAttribute(Collection<ConfigAttribute> config) {
private static @Nullable PreInvocationAttribute findPreInvocationAttribute(Collection<ConfigAttribute> config) {
for (ConfigAttribute attribute : config) {
if (attribute instanceof PreInvocationAttribute) {
return (PreInvocationAttribute) attribute;

9
core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java

@ -22,6 +22,9 @@ import java.util.ArrayList; @@ -22,6 +22,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.log.LogMessage;
import org.springframework.security.access.ConfigAttribute;
@ -54,6 +57,7 @@ import org.springframework.util.ClassUtils; @@ -54,6 +57,7 @@ import org.springframework.util.ClassUtils;
* {@link org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager}
* instead
*/
@NullUnmarked
@Deprecated
public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecurityMetadataSource {
@ -98,7 +102,7 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur @@ -98,7 +102,7 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
public @Nullable Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@ -108,7 +112,8 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur @@ -108,7 +112,8 @@ public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecur
* for the logic of this method. The ordering here is slightly different in that we
* consider method-specific annotations on an interface before class-level ones.
*/
private <A extends Annotation> A findAnnotation(Method method, Class<?> targetClass, Class<A> annotationClass) {
private <A extends Annotation> @Nullable A findAnnotation(Method method, Class<?> targetClass,
Class<A> annotationClass) {
// The method may be on an interface, but we need attributes from the target
// class.
// If the target class is null, the method will be unchanged.

9
core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.access.prepost;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.security.authorization.AuthorizationManager;
@ -29,9 +31,10 @@ import org.springframework.security.authorization.AuthorizationManager; @@ -29,9 +31,10 @@ import org.springframework.security.authorization.AuthorizationManager;
@Deprecated
public interface PrePostInvocationAttributeFactory extends AopInfrastructureBean {
PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, String filterObject,
String preAuthorizeAttribute);
PreInvocationAttribute createPreInvocationAttribute(@Nullable String preFilterAttribute,
@Nullable String filterObject, @Nullable String preAuthorizeAttribute);
PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute, String postAuthorizeAttribute);
PostInvocationAttribute createPostInvocationAttribute(@Nullable String postFilterAttribute,
@Nullable String postAuthorizeAttribute);
}

3
core/src/main/java/org/springframework/security/access/prepost/package-info.java

@ -21,4 +21,7 @@ @@ -21,4 +21,7 @@
* Other than the annotations themselves, the classes should be regarded as for internal
* framework use and are liable to change without notice.
*/
@NullMarked
package org.springframework.security.access.prepost;
import org.jspecify.annotations.NullMarked;

6
core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java

@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
package org.springframework.security.access.vote;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.AuthorizationServiceException;
@ -30,10 +32,12 @@ import org.springframework.util.Assert; @@ -30,10 +32,12 @@ import org.springframework.util.Assert;
* @deprecated Now used by only-deprecated classes. Generally speaking, in-memory ACL is
* no longer advised, so no replacement is planned at this point.
*/
@NullUnmarked
@Deprecated
public abstract class AbstractAclVoter implements AccessDecisionVoter<MethodInvocation> {
private Class<?> processDomainObjectClass;
@SuppressWarnings("NullAway.Init")
private @Nullable Class<?> processDomainObjectClass;
protected Object getDomainObjectInstance(MethodInvocation invocation) {
Object[] args = invocation.getArguments();

7
core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java

@ -18,6 +18,9 @@ package org.springframework.security.access.vote; @@ -18,6 +18,9 @@ package org.springframework.security.access.vote;
import java.util.Collection;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
@ -33,10 +36,12 @@ import org.springframework.util.Assert; @@ -33,10 +36,12 @@ import org.springframework.util.Assert;
* {@link org.springframework.security.authorization.AuthorityAuthorizationManager#setRoleHierarchy}
* instead
*/
@NullUnmarked
@Deprecated
public class RoleHierarchyVoter extends RoleVoter {
private RoleHierarchy roleHierarchy = null;
@SuppressWarnings("NullAway")
private @Nullable RoleHierarchy roleHierarchy = null;
public RoleHierarchyVoter(RoleHierarchy roleHierarchy) {
Assert.notNull(roleHierarchy, "RoleHierarchy must not be null");

3
core/src/main/java/org/springframework/security/access/vote/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Implements a vote-based approach to authorization decisions.
*/
@NullMarked
package org.springframework.security.access.vote;
import org.jspecify.annotations.NullMarked;

4
core/src/main/java/org/springframework/security/aot/hint/CoreSecurityRuntimeHints.java

@ -19,6 +19,8 @@ package org.springframework.security.aot.hint; @@ -19,6 +19,8 @@ package org.springframework.security.aot.hint;
import java.util.List;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@ -54,7 +56,7 @@ import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; @@ -54,7 +56,7 @@ import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
class CoreSecurityRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
registerExceptionEventsHints(hints);
registerExpressionEvaluationHints(hints);
registerMethodSecurityHints(hints);

4
core/src/main/java/org/springframework/security/aot/hint/OneTimeTokenRuntimeHints.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.aot.hint;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.jdbc.core.JdbcOperations;
@ -33,7 +35,7 @@ import org.springframework.security.authentication.ott.OneTimeTokenService; @@ -33,7 +35,7 @@ import org.springframework.security.authentication.ott.OneTimeTokenService;
class OneTimeTokenRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.resources().registerPattern("org/springframework/security/core/ott/jdbc/one-time-tokens-schema.sql");
}

20
core/src/main/java/org/springframework/security/aot/hint/package-info.java

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
/*
* Copyright 2002-2016 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.
*/
@NullMarked
package org.springframework.security.aot.hint;
import org.jspecify.annotations.NullMarked;

12
core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java

@ -21,6 +21,8 @@ import java.util.ArrayList; @@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.CredentialsContainer;
@ -41,7 +43,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre @@ -41,7 +43,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre
private final Collection<GrantedAuthority> authorities;
private Object details;
private @Nullable Object details;
private boolean authenticated = false;
@ -50,7 +52,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre @@ -50,7 +52,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre
* @param authorities the collection of <tt>GrantedAuthority</tt>s for the principal
* represented by this authentication object.
*/
public AbstractAuthenticationToken(Collection<? extends GrantedAuthority> authorities) {
public AbstractAuthenticationToken(@Nullable Collection<? extends GrantedAuthority> authorities) {
if (authorities == null) {
this.authorities = AuthorityUtils.NO_AUTHORITIES;
return;
@ -91,11 +93,11 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre @@ -91,11 +93,11 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre
}
@Override
public Object getDetails() {
public @Nullable Object getDetails() {
return this.details;
}
public void setDetails(Object details) {
public void setDetails(@Nullable Object details) {
this.details = details;
}
@ -111,7 +113,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre @@ -111,7 +113,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre
eraseSecret(this.details);
}
private void eraseSecret(Object secret) {
private void eraseSecret(@Nullable Object secret) {
if (secret instanceof CredentialsContainer container) {
container.eraseCredentials();
}

18
core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java

@ -18,6 +18,7 @@ package org.springframework.security.authentication; @@ -18,6 +18,7 @@ package org.springframework.security.authentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
@ -60,7 +61,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager @@ -60,7 +61,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager
private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
private ReactiveUserDetailsPasswordService userDetailsPasswordService;
private ReactiveUserDetailsPasswordService userDetailsPasswordService = ReactiveUserDetailsPasswordService.NOOP;
private Scheduler scheduler = Schedulers.boundedElastic();
@ -68,7 +69,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager @@ -68,7 +69,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager
private UserDetailsChecker postAuthenticationChecks = this::defaultPostAuthenticationChecks;
private ReactiveCompromisedPasswordChecker compromisedPasswordChecker;
private @Nullable ReactiveCompromisedPasswordChecker compromisedPasswordChecker;
private void defaultPreAuthenticationChecks(UserDetails user) {
if (!user.isAccountNonLocked()) {
@ -99,7 +100,8 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager @@ -99,7 +100,8 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
String username = authentication.getName();
String presentedPassword = (String) authentication.getCredentials();
String presentedPassword = (authentication.getCredentials() != null)
? authentication.getCredentials().toString() : null;
// @formatter:off
return retrieveUser(username)
.doOnNext(this.preAuthenticationChecks::check)
@ -113,7 +115,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager @@ -113,7 +115,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager
// @formatter:on
}
private Mono<Void> checkCompromisedPassword(String password) {
private Mono<Void> checkCompromisedPassword(@Nullable String password) {
if (this.compromisedPasswordChecker == null) {
return Mono.empty();
}
@ -123,9 +125,10 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager @@ -123,9 +125,10 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager
"The provided password is compromised, please change your password")));
}
private Mono<UserDetails> upgradeEncodingIfNecessary(UserDetails userDetails, String presentedPassword) {
boolean upgradeEncoding = this.userDetailsPasswordService != null
&& this.passwordEncoder.upgradeEncoding(userDetails.getPassword());
private Mono<UserDetails> upgradeEncodingIfNecessary(UserDetails userDetails, @Nullable String presentedPassword) {
String existingEncodedPassword = userDetails.getPassword();
boolean upgradeEncoding = existingEncodedPassword != null
&& this.passwordEncoder.upgradeEncoding(existingEncodedPassword);
if (upgradeEncoding) {
String newPassword = this.passwordEncoder.encode(presentedPassword);
return this.userDetailsPasswordService.updatePassword(userDetails, newPassword);
@ -170,6 +173,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager @@ -170,6 +173,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager
* @param userDetailsPasswordService the service to use
*/
public void setUserDetailsPasswordService(ReactiveUserDetailsPasswordService userDetailsPasswordService) {
Assert.notNull(userDetailsPasswordService, "userDetailsPasswordService cannot be null");
this.userDetailsPasswordService = userDetailsPasswordService;
}

4
core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.authentication;
import org.jspecify.annotations.Nullable;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
@ -45,7 +47,7 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider, @@ -45,7 +47,7 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider,
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}

13
core/src/main/java/org/springframework/security/authentication/AuthenticationObservationContext.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.security.authentication;
import io.micrometer.observation.Observation;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
@ -29,17 +30,17 @@ import org.springframework.util.Assert; @@ -29,17 +30,17 @@ import org.springframework.util.Assert;
*/
public class AuthenticationObservationContext extends Observation.Context {
private Authentication authenticationRequest;
private @Nullable Authentication authenticationRequest;
private Class<?> authenticationManager;
private @Nullable Class<?> authenticationManager;
private Authentication authenticationResult;
private @Nullable Authentication authenticationResult;
/**
* Get the {@link Authentication} request that was observed
* @return the observed {@link Authentication} request
*/
public Authentication getAuthenticationRequest() {
public @Nullable Authentication getAuthenticationRequest() {
return this.authenticationRequest;
}
@ -60,7 +61,7 @@ public class AuthenticationObservationContext extends Observation.Context { @@ -60,7 +61,7 @@ public class AuthenticationObservationContext extends Observation.Context {
* observed. In that case, this returns {@code null}.
* @return any observed {@link Authentication} result, {@code null} otherwise
*/
public Authentication getAuthenticationResult() {
public @Nullable Authentication getAuthenticationResult() {
return this.authenticationResult;
}
@ -76,7 +77,7 @@ public class AuthenticationObservationContext extends Observation.Context { @@ -76,7 +77,7 @@ public class AuthenticationObservationContext extends Observation.Context {
* Get the {@link AuthenticationManager} class that processed the authentication
* @return the observed {@link AuthenticationManager} class
*/
public Class<?> getAuthenticationManagerClass() {
public @Nullable Class<?> getAuthenticationManagerClass() {
return this.authenticationManager;
}

9
core/src/main/java/org/springframework/security/authentication/AuthenticationObservationConvention.java

@ -21,9 +21,7 @@ import java.util.Locale; @@ -21,9 +21,7 @@ import java.util.Locale;
import io.micrometer.common.KeyValues;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;
import org.jetbrains.annotations.NotNull;
import org.springframework.lang.NonNull;
import org.jspecify.annotations.NonNull;
/**
* An {@link ObservationConvention} for translating authentications into
@ -63,9 +61,8 @@ public final class AuthenticationObservationConvention @@ -63,9 +61,8 @@ public final class AuthenticationObservationConvention
/**
* {@inheritDoc}
*/
@NotNull
@Override
public KeyValues getLowCardinalityKeyValues(@NonNull AuthenticationObservationContext context) {
public @NonNull KeyValues getLowCardinalityKeyValues(@NonNull AuthenticationObservationContext context) {
return KeyValues.of("authentication.request.type", getAuthenticationType(context))
.and("authentication.method", getAuthenticationMethod(context))
.and("authentication.result.type", getAuthenticationResult(context))
@ -104,7 +101,7 @@ public final class AuthenticationObservationConvention @@ -104,7 +101,7 @@ public final class AuthenticationObservationConvention
* {@inheritDoc}
*/
@Override
public boolean supportsContext(@NotNull Observation.Context context) {
public boolean supportsContext(Observation.Context context) {
return context instanceof AuthenticationObservationContext;
}

4
core/src/main/java/org/springframework/security/authentication/AuthenticationProvider.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.authentication;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
@ -39,7 +41,7 @@ public interface AuthenticationProvider { @@ -39,7 +41,7 @@ public interface AuthenticationProvider {
* <code>Authentication</code> class will be tried.
* @throws AuthenticationException if authentication fails.
*/
Authentication authenticate(Authentication authentication) throws AuthenticationException;
@Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException;
/**
* Returns <code>true</code> if this <Code>AuthenticationProvider</code> supports the

4
core/src/main/java/org/springframework/security/authentication/AuthenticationServiceException.java

@ -18,6 +18,8 @@ package org.springframework.security.authentication; @@ -18,6 +18,8 @@ package org.springframework.security.authentication;
import java.io.Serial;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.AuthenticationException;
/**
@ -49,7 +51,7 @@ public class AuthenticationServiceException extends AuthenticationException { @@ -49,7 +51,7 @@ public class AuthenticationServiceException extends AuthenticationException {
* @param msg the detail message
* @param cause root cause
*/
public AuthenticationServiceException(String msg, Throwable cause) {
public AuthenticationServiceException(@Nullable String msg, Throwable cause) {
super(msg, cause);
}

10
core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java

@ -24,6 +24,7 @@ import java.util.Properties; @@ -24,6 +24,7 @@ import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
@ -71,13 +72,15 @@ public class DefaultAuthenticationEventPublisher @@ -71,13 +72,15 @@ public class DefaultAuthenticationEventPublisher
private final HashMap<String, Constructor<? extends AbstractAuthenticationEvent>> exceptionMappings = new HashMap<>();
private Constructor<? extends AbstractAuthenticationFailureEvent> defaultAuthenticationFailureEventConstructor;
private @Nullable Constructor<? extends AbstractAuthenticationFailureEvent> defaultAuthenticationFailureEventConstructor;
public DefaultAuthenticationEventPublisher() {
this(null);
this((event) -> {
});
}
public DefaultAuthenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
Assert.notNull(applicationEventPublisher, "applicationEventPublisher cannot be null");
this.applicationEventPublisher = applicationEventPublisher;
addMapping(BadCredentialsException.class.getName(), AuthenticationFailureBadCredentialsEvent.class);
addMapping(UsernameNotFoundException.class.getName(), AuthenticationFailureBadCredentialsEvent.class);
@ -123,7 +126,8 @@ public class DefaultAuthenticationEventPublisher @@ -123,7 +126,8 @@ public class DefaultAuthenticationEventPublisher
}
}
private Constructor<? extends AbstractAuthenticationEvent> getEventConstructor(AuthenticationException exception) {
private @Nullable Constructor<? extends AbstractAuthenticationEvent> getEventConstructor(
AuthenticationException exception) {
Constructor<? extends AbstractAuthenticationEvent> eventConstructor = this.exceptionMappings
.get(exception.getClass().getName());
return (eventConstructor != null) ? eventConstructor : this.defaultAuthenticationFailureEventConstructor;

4
core/src/main/java/org/springframework/security/authentication/InternalAuthenticationServiceException.java

@ -18,6 +18,8 @@ package org.springframework.security.authentication; @@ -18,6 +18,8 @@ package org.springframework.security.authentication;
import java.io.Serial;
import org.jspecify.annotations.Nullable;
/**
* <p>
* Thrown if an authentication request could not be processed due to a system problem that
@ -42,7 +44,7 @@ public class InternalAuthenticationServiceException extends AuthenticationServic @@ -42,7 +44,7 @@ public class InternalAuthenticationServiceException extends AuthenticationServic
@Serial
private static final long serialVersionUID = -6029644854192497840L;
public InternalAuthenticationServiceException(String message, Throwable cause) {
public InternalAuthenticationServiceException(@Nullable String message, Throwable cause) {
super(message, cause);
}

1
core/src/main/java/org/springframework/security/authentication/ObservationAuthenticationManager.java

@ -46,6 +46,7 @@ public final class ObservationAuthenticationManager implements AuthenticationMan @@ -46,6 +46,7 @@ public final class ObservationAuthenticationManager implements AuthenticationMan
}
@Override
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
AuthenticationObservationContext context = new AuthenticationObservationContext();
context.setAuthenticationRequest(authentication);

5
core/src/main/java/org/springframework/security/authentication/ProviderManager.java

@ -22,6 +22,7 @@ import java.util.List; @@ -22,6 +22,7 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
@ -97,7 +98,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar @@ -97,7 +98,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private AuthenticationManager parent;
private @Nullable AuthenticationManager parent;
private boolean eraseCredentialsAfterAuthentication = true;
@ -122,7 +123,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar @@ -122,7 +123,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
* @param providers the {@link AuthenticationProvider}s to use
* @param parent a parent {@link AuthenticationManager} to fall back to
*/
public ProviderManager(List<AuthenticationProvider> providers, AuthenticationManager parent) {
public ProviderManager(List<AuthenticationProvider> providers, @Nullable AuthenticationManager parent) {
Assert.notNull(providers, "providers list cannot be null");
this.providers = providers;
this.parent = parent;

4
core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationProvider.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.authentication;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
@ -49,7 +51,7 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider, @@ -49,7 +51,7 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}

14
core/src/main/java/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java

@ -18,6 +18,8 @@ package org.springframework.security.authentication; @@ -18,6 +18,8 @@ package org.springframework.security.authentication;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
@ -40,7 +42,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT @@ -40,7 +42,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
private final Object principal;
private Object credentials;
private @Nullable Object credentials;
/**
* This constructor can be safely used by any code that wishes to create a
@ -48,7 +50,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT @@ -48,7 +50,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
* will return <code>false</code>.
*
*/
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
public UsernamePasswordAuthenticationToken(Object principal, @Nullable Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
@ -64,7 +66,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT @@ -64,7 +66,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
* @param credentials
* @param authorities
*/
public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
public UsernamePasswordAuthenticationToken(Object principal, @Nullable Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
@ -81,7 +83,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT @@ -81,7 +83,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
*
* @since 5.7
*/
public static UsernamePasswordAuthenticationToken unauthenticated(Object principal, Object credentials) {
public static UsernamePasswordAuthenticationToken unauthenticated(Object principal, @Nullable Object credentials) {
return new UsernamePasswordAuthenticationToken(principal, credentials);
}
@ -94,13 +96,13 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT @@ -94,13 +96,13 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
*
* @since 5.7
*/
public static UsernamePasswordAuthenticationToken authenticated(Object principal, Object credentials,
public static UsernamePasswordAuthenticationToken authenticated(Object principal, @Nullable Object credentials,
Collection<? extends GrantedAuthority> authorities) {
return new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
}
@Override
public Object getCredentials() {
public @Nullable Object getCredentials() {
return this.credentials;
}

20
core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java

@ -18,6 +18,8 @@ package org.springframework.security.authentication.dao; @@ -18,6 +18,8 @@ package org.springframework.security.authentication.dao;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
@ -60,15 +62,16 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication @@ -60,15 +62,16 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
* {@link PasswordEncoder} implementations will short circuit if the password is not
* in a valid format.
*/
private volatile String userNotFoundEncodedPassword;
private volatile @Nullable String userNotFoundEncodedPassword;
private UserDetailsService userDetailsService;
private final UserDetailsService userDetailsService;
private UserDetailsPasswordService userDetailsPasswordService;
private UserDetailsPasswordService userDetailsPasswordService = UserDetailsPasswordService.NOOP;
private CompromisedPasswordChecker compromisedPasswordChecker;
private @Nullable CompromisedPasswordChecker compromisedPasswordChecker;
public DaoAuthenticationProvider(UserDetailsService userDetailsService) {
Assert.notNull(userDetailsService, "userDetailsService cannot be null");
this.userDetailsService = userDetailsService;
}
@ -120,14 +123,16 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication @@ -120,14 +123,16 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
@Override
protected Authentication createSuccessAuthentication(Object principal, Authentication authentication,
UserDetails user) {
Assert.notNull(authentication.getCredentials(), "Authentication.getCredentials() cannot be null");
String presentedPassword = authentication.getCredentials().toString();
boolean isPasswordCompromised = this.compromisedPasswordChecker != null
&& this.compromisedPasswordChecker.check(presentedPassword).isCompromised();
if (isPasswordCompromised) {
throw new CompromisedPasswordException("The provided password is compromised, please change your password");
}
boolean upgradeEncoding = this.userDetailsPasswordService != null
&& this.passwordEncoder.get().upgradeEncoding(user.getPassword());
String existingEncodedPassword = user.getPassword();
boolean upgradeEncoding = existingEncodedPassword != null && this.userDetailsPasswordService != null
&& this.passwordEncoder.get().upgradeEncoding(existingEncodedPassword);
if (upgradeEncoding) {
String newPassword = this.passwordEncoder.get().encode(presentedPassword);
user = this.userDetailsPasswordService.updatePassword(user, newPassword);
@ -143,6 +148,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication @@ -143,6 +148,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) {
if (authentication.getCredentials() != null) {
Assert.notNull(this.userNotFoundEncodedPassword, "userNotFoundEncodedPassword cannot be null");
String presentedPassword = authentication.getCredentials().toString();
this.passwordEncoder.get().matches(presentedPassword, this.userNotFoundEncodedPassword);
}
@ -170,6 +176,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication @@ -170,6 +176,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
}
public void setUserDetailsPasswordService(UserDetailsPasswordService userDetailsPasswordService) {
Assert.notNull(userDetailsPasswordService, "userDetailsPasswordService cannot be null");
this.userDetailsPasswordService = userDetailsPasswordService;
}
@ -180,6 +187,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication @@ -180,6 +187,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
* @since 6.3
*/
public void setCompromisedPasswordChecker(CompromisedPasswordChecker compromisedPasswordChecker) {
Assert.notNull(compromisedPasswordChecker, "compromisedPasswordChecker cannot be null");
this.compromisedPasswordChecker = compromisedPasswordChecker;
}

3
core/src/main/java/org/springframework/security/authentication/dao/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* An {@code AuthenticationProvider} which relies upon a data access object.
*/
@NullMarked
package org.springframework.security.authentication.dao;
import org.jspecify.annotations.NullMarked;

3
core/src/main/java/org/springframework/security/authentication/event/package-info.java

@ -22,4 +22,7 @@ @@ -22,4 +22,7 @@
* context. These events are received by all registered Spring
* <code>ApplicationListener</code>s.
*/
@NullMarked
package org.springframework.security.authentication.event;
import org.jspecify.annotations.NullMarked;

13
core/src/main/java/org/springframework/security/authentication/jaas/AbstractJaasAuthenticationProvider.java

@ -31,6 +31,7 @@ import javax.security.auth.login.LoginException; @@ -31,6 +31,7 @@ import javax.security.auth.login.LoginException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisher;
@ -119,11 +120,12 @@ import org.springframework.util.ObjectUtils; @@ -119,11 +120,12 @@ import org.springframework.util.ObjectUtils;
public abstract class AbstractJaasAuthenticationProvider implements AuthenticationProvider,
ApplicationEventPublisherAware, InitializingBean, ApplicationListener<SessionDestroyedEvent> {
private ApplicationEventPublisher applicationEventPublisher;
private ApplicationEventPublisher applicationEventPublisher = (event) -> {
};
private AuthorityGranter[] authorityGranters;
private AuthorityGranter[] authorityGranters = new AuthorityGranter[0];
private JaasAuthenticationCallbackHandler[] callbackHandlers;
private JaasAuthenticationCallbackHandler[] callbackHandlers = new JaasAuthenticationCallbackHandler[0];
protected final Log log = LogFactory.getLog(getClass());
@ -159,7 +161,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati @@ -159,7 +161,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
* loginContext.login() method fail.
*/
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
public @Nullable Authentication authenticate(Authentication auth) throws AuthenticationException {
if (!(auth instanceof UsernamePasswordAuthenticationToken request)) {
return null;
}
@ -303,6 +305,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati @@ -303,6 +305,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
* @see JaasAuthenticationProvider
*/
public void setAuthorityGranters(AuthorityGranter[] authorityGranters) {
Assert.notNull(authorityGranters, "authorityGranters cannot be null");
this.authorityGranters = authorityGranters;
}
@ -323,6 +326,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati @@ -323,6 +326,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
* @param callbackHandlers Array of JAASAuthenticationCallbackHandlers
*/
public void setCallbackHandlers(JaasAuthenticationCallbackHandler[] callbackHandlers) {
Assert.notNull(callbackHandlers, "callbackHandlers cannot be null");
this.callbackHandlers = callbackHandlers;
}
@ -354,6 +358,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati @@ -354,6 +358,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
Assert.notNull(applicationEventPublisher, "applicationEventPublisher cannot be null");
this.applicationEventPublisher = applicationEventPublisher;
}

1
core/src/main/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProvider.java

@ -87,6 +87,7 @@ import org.springframework.util.Assert; @@ -87,6 +87,7 @@ import org.springframework.util.Assert;
*/
public class DefaultJaasAuthenticationProvider extends AbstractJaasAuthenticationProvider {
@SuppressWarnings("NullAway.Init")
private Configuration configuration;
@Override

1
core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java

@ -143,6 +143,7 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid @@ -143,6 +143,7 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid
// exists for passivity
protected static final Log log = LogFactory.getLog(JaasAuthenticationProvider.class);
@SuppressWarnings("NullAway.Init")
private Resource loginConfig;
private boolean refreshConfigurationOnStartup = true;

6
core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java

@ -20,6 +20,8 @@ import java.util.List; @@ -20,6 +20,8 @@ import java.util.List;
import javax.security.auth.login.LoginContext;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
@ -36,12 +38,12 @@ public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken @@ -36,12 +38,12 @@ public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken
private final transient LoginContext loginContext;
public JaasAuthenticationToken(Object principal, Object credentials, LoginContext loginContext) {
public JaasAuthenticationToken(Object principal, @Nullable Object credentials, LoginContext loginContext) {
super(principal, credentials);
this.loginContext = loginContext;
}
public JaasAuthenticationToken(Object principal, Object credentials, List<GrantedAuthority> authorities,
public JaasAuthenticationToken(Object principal, @Nullable Object credentials, List<GrantedAuthority> authorities,
LoginContext loginContext) {
super(principal, credentials, authorities);
this.loginContext = loginContext;

2
core/src/main/java/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java

@ -21,6 +21,7 @@ import javax.security.auth.callback.NameCallback; @@ -21,6 +21,7 @@ import javax.security.auth.callback.NameCallback;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
/**
* The most basic Callbacks to be handled when using a LoginContext from JAAS, are the
@ -55,6 +56,7 @@ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandle @@ -55,6 +56,7 @@ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandle
if (principal instanceof UserDetails) {
return ((UserDetails) principal).getUsername();
}
Assert.notNull(principal, "principal cannot be null");
return principal.toString();
}

5
core/src/main/java/org/springframework/security/authentication/jaas/JaasPasswordCallbackHandler.java

@ -47,7 +47,10 @@ public class JaasPasswordCallbackHandler implements JaasAuthenticationCallbackHa @@ -47,7 +47,10 @@ public class JaasPasswordCallbackHandler implements JaasAuthenticationCallbackHa
@Override
public void handle(Callback callback, Authentication auth) {
if (callback instanceof PasswordCallback) {
((PasswordCallback) callback).setPassword(auth.getCredentials().toString().toCharArray());
Object credentials = auth.getCredentials();
if (credentials != null) {
((PasswordCallback) callback).setPassword(credentials.toString().toCharArray());
}
}
}

11
core/src/main/java/org/springframework/security/authentication/jaas/SecurityContextLoginModule.java

@ -25,6 +25,7 @@ import javax.security.auth.spi.LoginModule; @@ -25,6 +25,7 @@ import javax.security.auth.spi.LoginModule;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@ -60,9 +61,9 @@ public class SecurityContextLoginModule implements LoginModule { @@ -60,9 +61,9 @@ public class SecurityContextLoginModule implements LoginModule {
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private Authentication authen;
private @Nullable Authentication authen;
private Subject subject;
private @Nullable Subject subject;
private boolean ignoreMissingAuthentication = false;
@ -92,6 +93,7 @@ public class SecurityContextLoginModule implements LoginModule { @@ -92,6 +93,7 @@ public class SecurityContextLoginModule implements LoginModule {
if (this.authen == null) {
return false;
}
Assert.notNull(this.subject, "subject cannot be null");
this.subject.getPrincipals().add(this.authen);
return true;
}
@ -107,11 +109,11 @@ public class SecurityContextLoginModule implements LoginModule { @@ -107,11 +109,11 @@ public class SecurityContextLoginModule implements LoginModule {
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
Authentication getAuthentication() {
@Nullable Authentication getAuthentication() {
return this.authen;
}
Subject getSubject() {
@Nullable Subject getSubject() {
return this.subject;
}
@ -165,6 +167,7 @@ public class SecurityContextLoginModule implements LoginModule { @@ -165,6 +167,7 @@ public class SecurityContextLoginModule implements LoginModule {
if (this.authen == null) {
return false;
}
Assert.notNull(this.subject, "subject cannot be null");
this.subject.getPrincipals().remove(this.authen);
this.authen = null;
return true;

3
core/src/main/java/org/springframework/security/authentication/jaas/event/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* JAAS authentication events which can be published to the Spring application context by
* the JAAS authentication provider.
*/
@NullMarked
package org.springframework.security.authentication.jaas.event;
import org.jspecify.annotations.NullMarked;

8
core/src/main/java/org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.java

@ -22,6 +22,8 @@ import java.util.Map; @@ -22,6 +22,8 @@ import java.util.Map;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@ -37,7 +39,7 @@ import org.springframework.util.Assert; @@ -37,7 +39,7 @@ import org.springframework.util.Assert;
*/
public class InMemoryConfiguration extends Configuration {
private final AppConfigurationEntry[] defaultConfiguration;
private final AppConfigurationEntry @Nullable [] defaultConfiguration;
private final Map<String, AppConfigurationEntry[]> mappedConfigurations;
@ -71,14 +73,14 @@ public class InMemoryConfiguration extends Configuration { @@ -71,14 +73,14 @@ public class InMemoryConfiguration extends Configuration {
* {@link #getAppConfigurationEntry(String)}. Can be <code>null</code>.
*/
public InMemoryConfiguration(Map<String, AppConfigurationEntry[]> mappedConfigurations,
AppConfigurationEntry[] defaultConfiguration) {
AppConfigurationEntry @Nullable [] defaultConfiguration) {
Assert.notNull(mappedConfigurations, "mappedConfigurations cannot be null.");
this.mappedConfigurations = mappedConfigurations;
this.defaultConfiguration = defaultConfiguration;
}
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
public AppConfigurationEntry @Nullable [] getAppConfigurationEntry(String name) {
AppConfigurationEntry[] mappedResult = this.mappedConfigurations.get(name);
return (mappedResult != null) ? mappedResult : this.defaultConfiguration;
}

3
core/src/main/java/org/springframework/security/authentication/jaas/memory/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* An in memory JAAS implementation.
*/
@NullMarked
package org.springframework.security.authentication.jaas.memory;
import org.jspecify.annotations.NullMarked;

3
core/src/main/java/org/springframework/security/authentication/jaas/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* An authentication provider for JAAS.
*/
@NullMarked
package org.springframework.security.authentication.jaas;
import org.jspecify.annotations.NullMarked;

6
core/src/main/java/org/springframework/security/authentication/ott/InMemoryOneTimeTokenService.java

@ -22,7 +22,8 @@ import java.util.Map; @@ -22,7 +22,8 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.lang.NonNull;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@ -41,7 +42,6 @@ public final class InMemoryOneTimeTokenService implements OneTimeTokenService { @@ -41,7 +42,6 @@ public final class InMemoryOneTimeTokenService implements OneTimeTokenService {
private Clock clock = Clock.systemUTC();
@Override
@NonNull
public OneTimeToken generate(GenerateOneTimeTokenRequest request) {
String token = UUID.randomUUID().toString();
Instant expiresAt = this.clock.instant().plus(request.getExpiresIn());
@ -52,7 +52,7 @@ public final class InMemoryOneTimeTokenService implements OneTimeTokenService { @@ -52,7 +52,7 @@ public final class InMemoryOneTimeTokenService implements OneTimeTokenService {
}
@Override
public OneTimeToken consume(OneTimeTokenAuthenticationToken authenticationToken) {
public @Nullable OneTimeToken consume(OneTimeTokenAuthenticationToken authenticationToken) {
OneTimeToken ott = this.oneTimeTokenByToken.remove(authenticationToken.getTokenValue());
if (ott == null || isExpired(ott)) {
return null;

11
core/src/main/java/org/springframework/security/authentication/ott/JdbcOneTimeTokenService.java

@ -29,6 +29,7 @@ import java.util.function.Function; @@ -29,6 +29,7 @@ import java.util.function.Function;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
@ -68,7 +69,7 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo @@ -68,7 +69,7 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo
private Clock clock = Clock.systemUTC();
private ThreadPoolTaskScheduler taskScheduler;
private @Nullable ThreadPoolTaskScheduler taskScheduler;
private static final String DEFAULT_CLEANUP_CRON = "@hourly";
@ -144,7 +145,7 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo @@ -144,7 +145,7 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo
}
@Override
public OneTimeToken consume(OneTimeTokenAuthenticationToken authenticationToken) {
public @Nullable OneTimeToken consume(OneTimeTokenAuthenticationToken authenticationToken) {
Assert.notNull(authenticationToken, "authenticationToken cannot be null");
List<OneTimeToken> tokens = selectOneTimeToken(authenticationToken);
@ -177,7 +178,7 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo @@ -177,7 +178,7 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo
this.jdbcOperations.update(DELETE_ONE_TIME_TOKEN_SQL, pss);
}
private ThreadPoolTaskScheduler createTaskScheduler(String cleanupCron) {
private @Nullable ThreadPoolTaskScheduler createTaskScheduler(String cleanupCron) {
if (cleanupCron == null) {
return null;
}
@ -200,7 +201,9 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo @@ -200,7 +201,9 @@ public final class JdbcOneTimeTokenService implements OneTimeTokenService, Dispo
@Override
public void afterPropertiesSet() throws Exception {
this.taskScheduler.afterPropertiesSet();
if (this.taskScheduler != null) {
this.taskScheduler.afterPropertiesSet();
}
}
@Override

14
core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationToken.java

@ -20,6 +20,8 @@ import java.io.Serial; @@ -20,6 +20,8 @@ import java.io.Serial;
import java.util.Collection;
import java.util.Collections;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
@ -34,11 +36,11 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken @@ -34,11 +36,11 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
@Serial
private static final long serialVersionUID = -8691636031126328365L;
private final Object principal;
private @Nullable final Object principal;
private String tokenValue;
private @Nullable String tokenValue;
public OneTimeTokenAuthenticationToken(Object principal, String tokenValue) {
public OneTimeTokenAuthenticationToken(@Nullable Object principal, String tokenValue) {
super(Collections.emptyList());
this.tokenValue = tokenValue;
this.principal = principal;
@ -88,17 +90,17 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken @@ -88,17 +90,17 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken
* Returns the one-time token value
* @return
*/
public String getTokenValue() {
public @Nullable String getTokenValue() {
return this.tokenValue;
}
@Override
public Object getCredentials() {
public @Nullable Object getCredentials() {
return this.tokenValue;
}
@Override
public Object getPrincipal() {
public @Nullable Object getPrincipal() {
return this.principal;
}

7
core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenService.java

@ -16,8 +16,7 @@ @@ -16,8 +16,7 @@
package org.springframework.security.authentication.ott;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Interface for generating and consuming one-time tokens.
@ -33,7 +32,6 @@ public interface OneTimeTokenService { @@ -33,7 +32,6 @@ public interface OneTimeTokenService {
* generate the token
* @return the generated {@link OneTimeToken}, never {@code null}.
*/
@NonNull
OneTimeToken generate(GenerateOneTimeTokenRequest request);
/**
@ -42,7 +40,6 @@ public interface OneTimeTokenService { @@ -42,7 +40,6 @@ public interface OneTimeTokenService {
* value to be consumed
* @return the consumed {@link OneTimeToken} or {@code null} if the token is invalid
*/
@Nullable
OneTimeToken consume(OneTimeTokenAuthenticationToken authenticationToken);
@Nullable OneTimeToken consume(OneTimeTokenAuthenticationToken authenticationToken);
}

20
core/src/main/java/org/springframework/security/authentication/ott/package-info.java

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.
*/
@NullMarked
package org.springframework.security.authentication.ott;
import org.jspecify.annotations.NullMarked;

20
core/src/main/java/org/springframework/security/authentication/ott/reactive/package-info.java

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.
*/
@NullMarked
package org.springframework.security.authentication.ott.reactive;
import org.jspecify.annotations.NullMarked;

3
core/src/main/java/org/springframework/security/authentication/package-info.java

@ -26,4 +26,7 @@ @@ -26,4 +26,7 @@
* {@link org.springframework.security.authentication.AuthenticationProvider
* AuthenticationProvider}s to which it delegates authentication requests.
*/
@NullMarked
package org.springframework.security.authentication;
import org.jspecify.annotations.NullMarked;

9
core/src/main/java/org/springframework/security/authentication/password/CompromisedPasswordChecker.java

@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
package org.springframework.security.authentication.password;
import org.springframework.lang.NonNull;
import org.jspecify.annotations.Nullable;
/**
* An API for checking if a password has been compromised.
@ -27,11 +27,12 @@ import org.springframework.lang.NonNull; @@ -27,11 +27,12 @@ import org.springframework.lang.NonNull;
public interface CompromisedPasswordChecker {
/**
* Check whether the password is compromised
* Check whether the password is compromised. If password is null, then the return
* value must be false for {@link CompromisedPasswordDecision#isCompromised()} since a
* null password represents no password (e.g. the user leverages Passkeys instead).
* @param password the password to check
* @return a non-null {@link CompromisedPasswordDecision}
*/
@NonNull
CompromisedPasswordDecision check(String password);
CompromisedPasswordDecision check(@Nullable String password);
}

7
core/src/main/java/org/springframework/security/authentication/password/ReactiveCompromisedPasswordChecker.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.security.authentication.password;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
/**
@ -27,10 +28,12 @@ import reactor.core.publisher.Mono; @@ -27,10 +28,12 @@ import reactor.core.publisher.Mono;
public interface ReactiveCompromisedPasswordChecker {
/**
* Check whether the password is compromised
* Check whether the password is compromised. If password is null, then the return
* value must be false for {@link CompromisedPasswordDecision#isCompromised()} since a
* null password represents no password (e.g. the user leverages Passkeys instead).
* @param password the password to check
* @return a {@link Mono} containing the {@link CompromisedPasswordDecision}
*/
Mono<CompromisedPasswordDecision> check(String password);
Mono<CompromisedPasswordDecision> check(@Nullable String password);
}

20
core/src/main/java/org/springframework/security/authentication/password/package-info.java

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
/*
* Copyright 2002-2025 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.
*/
@NullMarked
package org.springframework.security.authentication.password;
import org.jspecify.annotations.NullMarked;

8
core/src/main/java/org/springframework/security/authorization/AuthorizationManager.java

@ -18,7 +18,8 @@ package org.springframework.security.authorization; @@ -18,7 +18,8 @@ package org.springframework.security.authorization;
import java.util.function.Supplier;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
@ -30,7 +31,7 @@ import org.springframework.security.core.Authentication; @@ -30,7 +31,7 @@ import org.springframework.security.core.Authentication;
* @author Evgeniy Cheban
*/
@FunctionalInterface
public interface AuthorizationManager<T> {
public interface AuthorizationManager<@Nullable T> {
/**
* Determines if access should be granted for a specific authentication and object.
@ -53,7 +54,6 @@ public interface AuthorizationManager<T> { @@ -53,7 +54,6 @@ public interface AuthorizationManager<T> {
* @return an {@link AuthorizationResult}
* @since 6.4
*/
@Nullable
AuthorizationResult authorize(Supplier<Authentication> authentication, T object);
@Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, T object);
}

13
core/src/main/java/org/springframework/security/authorization/AuthorizationObservationContext.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.security.authorization;
import io.micrometer.observation.Observation;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
@ -29,11 +30,13 @@ import org.springframework.util.Assert; @@ -29,11 +30,13 @@ import org.springframework.util.Assert;
*/
public class AuthorizationObservationContext<T> extends Observation.Context {
private Authentication authentication;
// FIXME: Should we make this non-null?
private @Nullable Authentication authentication;
private final T object;
private AuthorizationResult authorizationResult;
// FIXME: Should we make this non-null?
private @Nullable AuthorizationResult authorizationResult;
public AuthorizationObservationContext(T object) {
Assert.notNull(object, "object cannot be null");
@ -48,7 +51,7 @@ public class AuthorizationObservationContext<T> extends Observation.Context { @@ -48,7 +51,7 @@ public class AuthorizationObservationContext<T> extends Observation.Context {
* {@link Authentication}, this will return {@code null}.
* @return any observed {@link Authentication}, {@code null} otherwise
*/
public Authentication getAuthentication() {
public @Nullable Authentication getAuthentication() {
return this.authentication;
}
@ -73,7 +76,7 @@ public class AuthorizationObservationContext<T> extends Observation.Context { @@ -73,7 +76,7 @@ public class AuthorizationObservationContext<T> extends Observation.Context {
* @return the observed {@link AuthorizationResult}
* @since 6.4
*/
public AuthorizationResult getAuthorizationResult() {
public @Nullable AuthorizationResult getAuthorizationResult() {
return this.authorizationResult;
}
@ -82,7 +85,7 @@ public class AuthorizationObservationContext<T> extends Observation.Context { @@ -82,7 +85,7 @@ public class AuthorizationObservationContext<T> extends Observation.Context {
* @param authorizationResult the observed {@link AuthorizationResult}
* @since 6.4
*/
public void setAuthorizationResult(AuthorizationResult authorizationResult) {
public void setAuthorizationResult(@Nullable AuthorizationResult authorizationResult) {
this.authorizationResult = authorizationResult;
}

4
core/src/main/java/org/springframework/security/authorization/AuthorizationProxyFactory.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.security.authorization;
import org.jspecify.annotations.Nullable;
/**
* A factory for wrapping arbitrary objects in authorization-related advice
*
@ -37,6 +39,6 @@ public interface AuthorizationProxyFactory { @@ -37,6 +39,6 @@ public interface AuthorizationProxyFactory {
* @throws org.springframework.aop.framework.AopConfigException if a proxy cannot be
* created
*/
<T> T proxy(T object);
<T> @Nullable T proxy(@Nullable T object);
}

8
core/src/main/java/org/springframework/security/authorization/ObservationAuthorizationManager.java

@ -22,6 +22,7 @@ import io.micrometer.observation.Observation; @@ -22,6 +22,7 @@ import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;
import io.micrometer.observation.ObservationRegistry;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.Nullable;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
@ -62,7 +63,7 @@ public final class ObservationAuthorizationManager<T> @@ -62,7 +63,7 @@ public final class ObservationAuthorizationManager<T>
}
@Override
public AuthorizationResult authorize(Supplier<Authentication> authentication, T object) {
public @Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, T object) {
AuthorizationObservationContext<T> context = new AuthorizationObservationContext<>(object);
Supplier<Authentication> wrapped = () -> {
context.setAuthentication(authentication.get());
@ -109,12 +110,13 @@ public final class ObservationAuthorizationManager<T> @@ -109,12 +110,13 @@ public final class ObservationAuthorizationManager<T>
}
@Override
public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
public @Nullable Object handleDeniedInvocation(MethodInvocation methodInvocation,
AuthorizationResult authorizationResult) {
return this.handler.handleDeniedInvocation(methodInvocation, authorizationResult);
}
@Override
public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
public @Nullable Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
AuthorizationResult authorizationResult) {
return this.handler.handleDeniedInvocationResult(methodInvocationResult, authorizationResult);
}

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

Loading…
Cancel
Save