diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java index 92f6e8ee..41a0bc0b 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java @@ -18,11 +18,13 @@ package org.springframework.ws.soap.security; import java.util.Iterator; import java.util.Locale; +import java.util.Objects; import javax.xml.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; import org.springframework.ws.client.WebServiceClientException; @@ -69,7 +71,7 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter private boolean skipValidationIfNoHeaderPresent = false; - private EndpointExceptionResolver exceptionResolver; + private @Nullable EndpointExceptionResolver exceptionResolver; /** * Indicates whether server-side incoming request are to be validated. Defaults to @@ -197,7 +199,7 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter } @Override - public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + public void afterCompletion(MessageContext messageContext, Object endpoint, @Nullable Exception ex) { cleanUp(); } @@ -279,7 +281,8 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter } @Override - public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException { + public void afterCompletion(MessageContext messageContext, @Nullable Exception ex) + throws WebServiceClientException { cleanUp(); } @@ -320,7 +323,7 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter this.logger.debug("No exception resolver present, creating basic soap fault"); } SoapBody response = ((SoapMessage) messageContext.getResponse()).getSoapBody(); - response.addClientOrSenderFault(ex.getMessage(), Locale.ENGLISH); + response.addClientOrSenderFault(Objects.requireNonNull(ex.getMessage()), Locale.ENGLISH); } return false; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityException.java index 891c7d36..e43828f9 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityException.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityException.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.security; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.WebServiceException; /** @@ -32,7 +34,7 @@ public abstract class WsSecurityException extends WebServiceException { super(msg); } - public WsSecurityException(String msg, Throwable ex) { + public WsSecurityException(@Nullable String msg, Throwable ex) { super(msg, ex); } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecuritySecurementException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecuritySecurementException.java index c799f953..d9d77f5b 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecuritySecurementException.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecuritySecurementException.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.security; +import org.jspecify.annotations.Nullable; + /** * Exception indicating that something went wrong during the securement of a message. *

@@ -33,7 +35,7 @@ public abstract class WsSecuritySecurementException extends WsSecurityException super(msg); } - public WsSecuritySecurementException(String msg, Throwable ex) { + public WsSecuritySecurementException(@Nullable String msg, Throwable ex) { super(msg, ex); } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityValidationException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityValidationException.java index 13d03456..3ea7332f 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityValidationException.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/WsSecurityValidationException.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.security; +import org.jspecify.annotations.Nullable; + /** * Exception indicating that something went wrong during the validation of a message. *

@@ -33,7 +35,7 @@ public abstract class WsSecurityValidationException extends WsSecurityException super(msg); } - public WsSecurityValidationException(String msg, Throwable ex) { + public WsSecurityValidationException(@Nullable String msg, Throwable ex) { super(msg, ex); } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/callback/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/callback/package-info.java index c5e8d259..8f5908a0 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/callback/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/callback/package-info.java @@ -17,4 +17,7 @@ /** * Contains generic {@code CallbackHandler} implementations. */ +@NullMarked package org.springframework.ws.soap.security.callback; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/package-info.java index 2d06a371..9ad0b3e9 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/package-info.java @@ -18,4 +18,7 @@ * Provides WS-Security implementation classes. Contains the * {@code AbstractWsSecurityInterceptor} and exceptions. */ +@NullMarked package org.springframework.ws.soap.security; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyManagersFactoryBean.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyManagersFactoryBean.java index a19b3cef..14876a94 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyManagersFactoryBean.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyManagersFactoryBean.java @@ -21,6 +21,8 @@ import java.security.KeyStore; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.StringUtils; @@ -38,21 +40,21 @@ import org.springframework.util.StringUtils; */ public class KeyManagersFactoryBean implements FactoryBean, InitializingBean { - private KeyManager[] keyManagers; + private KeyManager @Nullable [] keyManagers; - private KeyStore keyStore; + private @Nullable KeyStore keyStore; - private String algorithm; + private @Nullable String algorithm; - private String provider; + private @Nullable String provider; - private char[] password; + private char @Nullable [] password; /** * Sets the password to use for integrity checking. If this property is not set, then * integrity checking is not performed. */ - public void setPassword(String password) { + public void setPassword(@Nullable String password) { if (password != null) { this.password = password.toCharArray(); } @@ -84,7 +86,7 @@ public class KeyManagersFactoryBean implements FactoryBean, Initia } @Override - public KeyManager[] getObject() throws Exception { + public KeyManager @Nullable [] getObject() throws Exception { return this.keyManagers; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java index b1697543..214acbae 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java @@ -23,10 +23,12 @@ import java.security.KeyStore; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -45,22 +47,22 @@ public class KeyStoreFactoryBean implements FactoryBean, InitializingB private static final Log logger = LogFactory.getLog(KeyStoreFactoryBean.class); - private KeyStore keyStore; + private @Nullable KeyStore keyStore; - private String type; + private @Nullable String type; - private String provider; + private @Nullable String provider; - private Resource location; + private @Nullable Resource location; - private char[] password; + private char @Nullable [] password; /** * Sets the location of the key store to use. If this is not set, a new, empty key * store will be used. * @see KeyStore#load(java.io.InputStream,char[]) */ - public void setLocation(Resource location) { + public void setLocation(@Nullable Resource location) { this.location = location; } @@ -68,7 +70,7 @@ public class KeyStoreFactoryBean implements FactoryBean, InitializingB * Sets the password to use for integrity checking. If this property is not set, then * integrity checking is not performed. */ - public void setPassword(String password) { + public void setPassword(@Nullable String password) { if (password != null) { this.password = password.toCharArray(); } @@ -86,12 +88,13 @@ public class KeyStoreFactoryBean implements FactoryBean, InitializingB * used. * @see KeyStore#getDefaultType() */ - public void setType(String type) { + public void setType(@Nullable String type) { this.type = type; } @Override public KeyStore getObject() { + Assert.state(this.keyStore != null, "KeyStore has not been initialized"); return this.keyStore; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/TrustManagersFactoryBean.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/TrustManagersFactoryBean.java index 354fd3fa..4370a5f8 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/TrustManagersFactoryBean.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/TrustManagersFactoryBean.java @@ -21,6 +21,8 @@ import java.security.KeyStore; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.StringUtils; @@ -37,13 +39,13 @@ import org.springframework.util.StringUtils; */ public class TrustManagersFactoryBean implements FactoryBean, InitializingBean { - private TrustManager[] trustManagers; + private TrustManager @Nullable [] trustManagers; - private KeyStore keyStore; + private @Nullable KeyStore keyStore; - private String algorithm; + private @Nullable String algorithm; - private String provider; + private @Nullable String provider; /** * Sets the provider of the trust manager to use. If this is not set, the default is @@ -71,7 +73,7 @@ public class TrustManagersFactoryBean implements FactoryBean, In } @Override - public TrustManager[] getObject() throws Exception { + public TrustManager @Nullable [] getObject() throws Exception { return this.trustManagers; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/package-info.java index 9281d12d..d7b3f27b 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/support/package-info.java @@ -17,4 +17,7 @@ /** * Contains support classes for handling WS-Security messages. */ +@NullMarked package org.springframework.ws.soap.security.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jHandler.java index 8ec9b85f..9e0324c5 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jHandler.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jHandler.java @@ -26,6 +26,7 @@ import org.apache.wss4j.dom.engine.WSSecurityEngineResult; import org.apache.wss4j.dom.handler.HandlerAction; import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.dom.handler.WSHandler; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.springframework.util.StringUtils; @@ -45,11 +46,11 @@ class Wss4jHandler extends WSHandler { /** Keys are constants from {@link ConfigurationConstants}; values are strings. */ private final Properties options = new Properties(); - private String securementPassword; + private @Nullable String securementPassword; - private Crypto securementEncryptionCrypto; + private @Nullable Crypto securementEncryptionCrypto; - private Crypto securementSignatureCrypto; + private @Nullable Crypto securementSignatureCrypto; Wss4jHandler() { // set up default handler properties @@ -94,7 +95,7 @@ class Wss4jHandler extends WSHandler { } @Override - public String getPassword(Object msgContext) { + public @Nullable String getPassword(Object msgContext) { String contextPassword = (String) getProperty(msgContext, Wss4jSecurityInterceptor.SECUREMENT_PASSWORD_PROPERTY_NAME); if (StringUtils.hasLength(contextPassword)) { @@ -104,17 +105,17 @@ class Wss4jHandler extends WSHandler { } @Override - public Object getProperty(Object msgContext, String key) { + public @Nullable Object getProperty(Object msgContext, String key) { return ((MessageContext) msgContext).getProperty(key); } @Override - protected Crypto loadEncryptionCrypto(RequestData reqData) throws WSSecurityException { + protected @Nullable Crypto loadEncryptionCrypto(RequestData reqData) throws WSSecurityException { return this.securementEncryptionCrypto; } @Override - public Crypto loadSignatureCrypto(RequestData reqData) throws WSSecurityException { + public @Nullable Crypto loadSignatureCrypto(RequestData reqData) throws WSSecurityException { return this.securementSignatureCrypto; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityInterceptor.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityInterceptor.java index 11f59338..a0392a0a 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityInterceptor.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityInterceptor.java @@ -22,6 +22,7 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.regex.Pattern; import javax.security.auth.callback.Callback; @@ -46,6 +47,7 @@ import org.apache.wss4j.dom.validate.Credential; import org.apache.wss4j.dom.validate.SignatureTrustValidator; import org.apache.wss4j.dom.validate.TimestampValidator; import org.apache.wss4j.dom.validate.Validator; +import org.jspecify.annotations.Nullable; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -54,6 +56,7 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; +import org.springframework.ws.soap.SoapHeader; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor; import org.springframework.ws.soap.security.WsSecuritySecurementException; @@ -160,21 +163,21 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl */ public static final String SECUREMENT_PASSWORD_PROPERTY_NAME = "Wss4jSecurityInterceptor.securementPassword"; - private String securementActions; + private @Nullable String securementActions; - private String securementUsername; + private @Nullable String securementUsername; - private CallbackHandler validationCallbackHandler; + private @Nullable CallbackHandler validationCallbackHandler; - private String validationActions; + private @Nullable String validationActions; - private List validationActionsVector; + private List validationActionsVector = Collections.emptyList(); - private String validationActor; + private @Nullable String validationActor; - private Crypto validationDecryptionCrypto; + private @Nullable Crypto validationDecryptionCrypto; - private Crypto validationSignatureCrypto; + private @Nullable Crypto validationSignatureCrypto; private boolean timestampStrict = true; @@ -186,7 +189,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl private int futureTimeToLive = 60; - private WSSConfig wssConfig; + private @Nullable WSSConfig wssConfig; private final Wss4jHandler handler = new Wss4jHandler(); @@ -200,9 +203,9 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl private boolean securementUseDerivedKey; - private CallbackHandler samlCallbackHandler; + private @Nullable CallbackHandler samlCallbackHandler; - private CallbackHandler attachmentCallbackHandler; + private @Nullable CallbackHandler attachmentCallbackHandler; // Allow RSA 15 to maintain default behavior private boolean allowRSA15KeyTransportAlgorithm = true; @@ -871,7 +874,10 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl soapMessage.setDocument(envelopeAsDocument); if (this.getRemoveSecurityHeader()) { - soapMessage.getEnvelope().getHeader().removeHeaderElement(WS_SECURITY_NAME); + SoapHeader header = soapMessage.getEnvelope().getHeader(); + if (header != null) { + header.removeHeaderElement(WS_SECURITY_NAME); + } } } @@ -973,7 +979,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl if (principal instanceof WSUsernameTokenPrincipalImpl usernameTokenPrincipal) { UsernameTokenPrincipalCallback callback = new UsernameTokenPrincipalCallback(usernameTokenPrincipal); try { - this.validationCallbackHandler.handle(new Callback[] { callback }); + Objects.requireNonNull(this.validationCallbackHandler).handle(new Callback[] { callback }); } catch (IOException ex) { this.logger.warn("Principal callback resulted in IOException", ex); diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecuritySecurementException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecuritySecurementException.java index 60a09521..e2a41637 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecuritySecurementException.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecuritySecurementException.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.security.wss4j2; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.security.WsSecuritySecurementException; /** @@ -33,7 +35,7 @@ public class Wss4jSecuritySecurementException extends WsSecuritySecurementExcept super(msg); } - public Wss4jSecuritySecurementException(String msg, Throwable ex) { + public Wss4jSecuritySecurementException(@Nullable String msg, Throwable ex) { super(msg, ex); } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityValidationException.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityValidationException.java index d164f9d8..29c12f6a 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityValidationException.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/Wss4jSecurityValidationException.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.security.wss4j2; +import org.jspecify.annotations.Nullable; + import org.springframework.ws.soap.security.WsSecurityValidationException; /** @@ -33,7 +35,7 @@ public class Wss4jSecurityValidationException extends WsSecurityValidationExcept super(msg); } - public Wss4jSecurityValidationException(String msg, Throwable ex) { + public Wss4jSecurityValidationException(@Nullable String msg, Throwable ex) { super(msg, ex); } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/KeyStoreCallbackHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/KeyStoreCallbackHandler.java index 6fd23e93..af35954a 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/KeyStoreCallbackHandler.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/KeyStoreCallbackHandler.java @@ -22,10 +22,12 @@ import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; +import java.util.Objects; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.wss4j.common.ext.WSPasswordCallback; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.InitializingBean; import org.springframework.ws.soap.security.support.KeyStoreUtils; @@ -43,10 +45,11 @@ import org.springframework.ws.soap.security.support.KeyStoreUtils; */ public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler implements InitializingBean { - private String privateKeyPassword; + private @Nullable String privateKeyPassword; - private char[] symmetricKeyPassword; + private char @Nullable [] symmetricKeyPassword; + @SuppressWarnings("NullAway.Init") private KeyStore keyStore; /** @@ -75,7 +78,7 @@ public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler i try { key = this.keyStore.getKey(id, (this.symmetricKeyPassword != null) ? this.symmetricKeyPassword - : this.privateKeyPassword.toCharArray()); + : Objects.requireNonNull(this.privateKeyPassword).toCharArray()); } catch (UnrecoverableKeyException | KeyStoreException | NoSuchAlgorithmException ex) { throw new IOException("Could not get key", ex); @@ -93,7 +96,7 @@ public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler i * Sets the password used to retrieve private keys from the keystore. This property is * required for decryption based on private keys, and signing. */ - public void setPrivateKeyPassword(String privateKeyPassword) { + public void setPrivateKeyPassword(@Nullable String privateKeyPassword) { if (privateKeyPassword != null) { this.privateKeyPassword = privateKeyPassword; } @@ -104,7 +107,7 @@ public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler i * property is not set, it defaults to the private key password. * @see #setPrivateKeyPassword(String) */ - public void setSymmetricKeyPassword(String symmetricKeyPassword) { + public void setSymmetricKeyPassword(@Nullable String symmetricKeyPassword) { if (symmetricKeyPassword != null) { this.symmetricKeyPassword = symmetricKeyPassword.toCharArray(); } @@ -116,7 +119,7 @@ public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler i loadDefaultKeyStore(); } if (this.symmetricKeyPassword == null) { - this.symmetricKeyPassword = this.privateKeyPassword.toCharArray(); + this.symmetricKeyPassword = Objects.requireNonNull(this.privateKeyPassword).toCharArray(); } } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/SpringSecurityPasswordValidationCallbackHandler.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/SpringSecurityPasswordValidationCallbackHandler.java index 0e4f8c72..3851814a 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/SpringSecurityPasswordValidationCallbackHandler.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/SpringSecurityPasswordValidationCallbackHandler.java @@ -17,11 +17,13 @@ package org.springframework.ws.soap.security.wss4j2.callback; import java.io.IOException; +import java.util.Objects; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.wss4j.common.ext.WSPasswordCallback; import org.apache.wss4j.common.principal.WSUsernameTokenPrincipalImpl; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; @@ -53,7 +55,7 @@ public class SpringSecurityPasswordValidationCallbackHandler extends AbstractWsP private UserCache userCache = new NullUserCache(); - private UserDetailsService userDetailsService; + private @Nullable UserDetailsService userDetailsService; /** Sets the users cache. Not required, but can benefit performance. */ public void setUserCache(UserCache userCache) { @@ -92,7 +94,7 @@ public class SpringSecurityPasswordValidationCallbackHandler extends AbstractWsP UserDetails user = loadUserDetails(callback.getPrincipal().getName()); WSUsernameTokenPrincipalImpl principal = callback.getPrincipal(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(principal, - principal.getPassword(), user.getAuthorities()); + principal.getPassword(), (user != null) ? user.getAuthorities() : null); if (this.logger.isDebugEnabled()) { this.logger.debug("Authentication success: " + authRequest); } @@ -105,12 +107,12 @@ public class SpringSecurityPasswordValidationCallbackHandler extends AbstractWsP SecurityContextHolder.clearContext(); } - private UserDetails loadUserDetails(String username) throws DataAccessException { + private @Nullable UserDetails loadUserDetails(String username) throws DataAccessException { UserDetails user = this.userCache.getUserFromCache(username); if (user == null) { try { - user = this.userDetailsService.loadUserByUsername(username); + user = Objects.requireNonNull(this.userDetailsService).loadUserByUsername(username); } catch (UsernameNotFoundException notFound) { if (this.logger.isDebugEnabled()) { diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/package-info.java index 36f8d35a..4c1cd15a 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/callback/package-info.java @@ -17,4 +17,7 @@ /** * Contains {@code CallbackHandler} implementations for WSS4J 2.0+. */ +@NullMarked package org.springframework.ws.soap.security.wss4j2.callback; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/package-info.java index e3313c8f..2ace1d4e 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/package-info.java @@ -18,4 +18,7 @@ * Contains classes for using the Apache WSS4J * 2.0+ WS-Security implementation within Spring-WS. */ +@NullMarked package org.springframework.ws.soap.security.wss4j2; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/CryptoFactoryBean.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/CryptoFactoryBean.java index d50782bc..ee353aa6 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/CryptoFactoryBean.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/CryptoFactoryBean.java @@ -22,6 +22,7 @@ import java.util.Properties; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.crypto.CryptoFactory; import org.apache.wss4j.common.crypto.Merlin; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; @@ -46,7 +47,7 @@ public class CryptoFactoryBean implements FactoryBean, InitializingBean private final Properties configuration = new Properties(); - private Crypto crypto; + private @Nullable Crypto crypto; private static final String CRYPTO_PROVIDER_PROPERTY = "org.apache.wss4j.crypto.provider"; @@ -179,7 +180,7 @@ public class CryptoFactoryBean implements FactoryBean, InitializingBean } @Override - public Crypto getObject() throws Exception { + public @Nullable Crypto getObject() throws Exception { return this.crypto; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/package-info.java index b65aaa60..53704286 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/wss4j2/support/package-info.java @@ -17,4 +17,7 @@ /** * Contains support classes for working with WSS4J 2.0+. */ +@NullMarked package org.springframework.ws.soap.security.wss4j2.support; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationProvider.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationProvider.java index a4058909..9c885356 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationProvider.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationProvider.java @@ -20,6 +20,7 @@ import java.security.cert.X509Certificate; 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; @@ -56,6 +57,7 @@ public class X509AuthenticationProvider implements AuthenticationProvider, Initi protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + @SuppressWarnings("NullAway.Init") private X509AuthoritiesPopulator x509AuthoritiesPopulator; private X509UserCache userCache = new NullX509UserCache(); @@ -88,7 +90,7 @@ public class X509AuthenticationProvider implements AuthenticationProvider, Initi * authentication request. */ @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { + public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationToken.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationToken.java index 0661114e..97f7e500 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationToken.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/X509AuthenticationToken.java @@ -20,6 +20,8 @@ import java.io.Serial; import java.security.cert.X509Certificate; import java.util.Collection; +import org.jspecify.annotations.Nullable; + import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; @@ -39,7 +41,7 @@ public class X509AuthenticationToken extends AbstractAuthenticationToken { @Serial private static final long serialVersionUID = 1L; - private Object principal; + private @Nullable Object principal; private final X509Certificate credentials; @@ -82,7 +84,7 @@ public class X509AuthenticationToken extends AbstractAuthenticationToken { } @Override - public Object getPrincipal() { + public @Nullable Object getPrincipal() { return this.principal; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/NullX509UserCache.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/NullX509UserCache.java index 15c47b97..05cc0374 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/NullX509UserCache.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/NullX509UserCache.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.security.x509.cache; import java.security.cert.X509Certificate; +import org.jspecify.annotations.Nullable; + import org.springframework.security.core.userdetails.UserDetails; /** @@ -34,7 +36,7 @@ public class NullX509UserCache implements X509UserCache { // ======================================================================================================== @Override - public UserDetails getUserFromCache(X509Certificate certificate) { + public @Nullable UserDetails getUserFromCache(X509Certificate certificate) { return null; } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/SpringBasedX509UserCache.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/SpringBasedX509UserCache.java index 78ee5040..4a6a7a59 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/SpringBasedX509UserCache.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/SpringBasedX509UserCache.java @@ -20,6 +20,7 @@ import java.security.cert.X509Certificate; 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.cache.Cache; @@ -40,6 +41,7 @@ public class SpringBasedX509UserCache implements X509UserCache, InitializingBean private static final Log logger = LogFactory.getLog(SpringBasedX509UserCache.class); + @SuppressWarnings("NullAway.Init") private Cache cache; @Override @@ -48,13 +50,13 @@ public class SpringBasedX509UserCache implements X509UserCache, InitializingBean } @Override - public UserDetails getUserFromCache(X509Certificate userCert) { + public @Nullable UserDetails getUserFromCache(X509Certificate userCert) { if (logger.isDebugEnabled()) { String subjectDN = "unknown"; - if ((userCert != null) && (userCert.getSubjectX500Principal() != null)) { + if (userCert.getSubjectX500Principal() != null) { subjectDN = userCert.getSubjectX500Principal().toString(); } diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/X509UserCache.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/X509UserCache.java index f42fdb3f..ee41a248 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/X509UserCache.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/X509UserCache.java @@ -18,6 +18,8 @@ package org.springframework.ws.soap.security.x509.cache; import java.security.cert.X509Certificate; +import org.jspecify.annotations.Nullable; + import org.springframework.security.core.userdetails.UserDetails; /** @@ -39,7 +41,7 @@ public interface X509UserCache { // ~ Methods // ======================================================================================================== - UserDetails getUserFromCache(X509Certificate userCertificate); + @Nullable UserDetails getUserFromCache(X509Certificate userCertificate); void putUserInCache(X509Certificate key, UserDetails user); diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/package-info.java index f7743d9a..00d23fe2 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/cache/package-info.java @@ -17,4 +17,7 @@ /** * Caching support for X.509 client certificates. */ +@NullMarked package org.springframework.ws.soap.security.x509.cache; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/package-info.java index c47e760f..8ceaf9d4 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/package-info.java @@ -17,4 +17,7 @@ /** * X.509 client-certificate authentication support. */ +@NullMarked package org.springframework.ws.soap.security.x509; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/DaoX509AuthoritiesPopulator.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/DaoX509AuthoritiesPopulator.java index 29fbddc2..62ce45e6 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/DaoX509AuthoritiesPopulator.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/DaoX509AuthoritiesPopulator.java @@ -50,10 +50,12 @@ public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator, In protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + @SuppressWarnings("NullAway.Init") private Pattern subjectDNPattern; private String subjectDNRegex = "CN=(.*?),"; + @SuppressWarnings("NullAway.Init") private UserDetailsService userDetailsService; // ~ Methods diff --git a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/package-info.java b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/package-info.java index 1a7d85d3..367685f1 100644 --- a/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/package-info.java +++ b/spring-ws-security/src/main/java/org/springframework/ws/soap/security/x509/populator/package-info.java @@ -17,4 +17,7 @@ /** * User details popular for X.509 client certificates. */ +@NullMarked package org.springframework.ws.soap.security.x509.populator; + +import org.jspecify.annotations.NullMarked;