SWS-559 - Upgrade Spring Security to 3.0.2

This commit is contained in:
Tareq Abedrabbo
2010-05-20 10:18:13 +00:00
parent 3b8661d3ae
commit c4046ed29c
30 changed files with 725 additions and 139 deletions

View File

@@ -538,7 +538,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>2.0.5.RELEASE</version>
<version>3.0.2.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
@@ -546,15 +546,10 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core-tiger</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>2.0.5.RELEASE</version>
<version>3.0.2.RELEASE</version>
<classifier>tests</classifier>
<exclusions>
<exclusion>
@@ -562,7 +557,14 @@
<artifactId>spring-support</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependency>
<!-- X.509 dependencies -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.0.1</version>
<optional>true</optional>
</dependency>
<!-- JEE dependencies -->
<dependency>
<groupId>javax.xml.soap</groupId>

View File

@@ -408,7 +408,7 @@
<artifactItem>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>2.0.5.RELEASE</version>
<version>3.0.2.RELEASE</version>
<outputDirectory>${project.build.directory}/dependency/spring-security/</outputDirectory>
</artifactItem>
<!--Java EE-->

View File

@@ -246,10 +246,6 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core-tiger</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
@@ -269,7 +265,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>2.0.5.RELEASE</version>
<version>3.0.2.RELEASE</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>

View File

@@ -16,9 +16,12 @@
package org.springframework.ws.samples.airline.security;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;
/**
@@ -31,14 +34,17 @@ public class FrequentFlyerDetails implements UserDetails {
private FrequentFlyer frequentFlyer;
public static final GrantedAuthority[] GRANTED_AUTHORITIES =
new GrantedAuthority[]{new GrantedAuthorityImpl("ROLE_FREQUENT_FLYER")};
public static final Collection<GrantedAuthority> GRANTED_AUTHORITIES =
new ArrayList<GrantedAuthority>();
{
GRANTED_AUTHORITIES.add(new GrantedAuthorityImpl("ROLE_FREQUENT_FLYER"));
};
public FrequentFlyerDetails(FrequentFlyer frequentFlyer) {
this.frequentFlyer = frequentFlyer;
}
public GrantedAuthority[] getAuthorities() {
public Collection<GrantedAuthority> getAuthorities() {
return GRANTED_AUTHORITIES;
}

View File

@@ -17,12 +17,12 @@
package org.springframework.ws.samples.airline.security;
import org.springframework.dao.DataAccessException;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ws.samples.airline.dao.FrequentFlyerDao;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;

View File

@@ -23,7 +23,7 @@ import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.annotation.Secured;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

View File

@@ -19,11 +19,11 @@ package org.springframework.ws.samples.airline.security;
import junit.framework.TestCase;
import static org.easymock.EasyMock.*;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.context.SecurityContextImpl;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.ws.samples.airline.dao.FrequentFlyerDao;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;
@@ -42,7 +42,7 @@ public class SpringFrequentFlyerSecurityServiceTest extends TestCase {
public void testGetCurrentlyAuthenticatedFrequentFlyer() throws Exception {
FrequentFlyer frequentFlyer = new FrequentFlyer("john");
FrequentFlyerDetails detail = new FrequentFlyerDetails(frequentFlyer);
TestingAuthenticationToken token = new TestingAuthenticationToken(detail, null, (GrantedAuthority[])null);
TestingAuthenticationToken token = new TestingAuthenticationToken(detail, null, new GrantedAuthority[]{});
SecurityContext context = new SecurityContextImpl();
context.setAuthentication(token);
SecurityContextHolder.setContext(context);
@@ -60,4 +60,4 @@ public class SpringFrequentFlyerSecurityServiceTest extends TestCase {
assertEquals("Invalid result", frequentFlyer, result);
verify(flyerDaoMock);
}
}
}

View File

@@ -107,6 +107,11 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<!-- X.509 dependencies -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<optional>true</optional>
</dependency>
<!-- JEE dependencies -->
@@ -118,7 +123,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>2.0.5.RELEASE</version>
<version>3.0.2.RELEASE</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>

View File

@@ -15,11 +15,11 @@
package org.springframework.ws.soap.security.support;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.LockedException;
import org.springframework.security.DisabledException;
import org.springframework.security.AccountExpiredException;
import org.springframework.security.CredentialsExpiredException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.CredentialsExpiredException;
/**
* Generic utility methods for Spring Security

View File

@@ -24,13 +24,13 @@ import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.dao.UserCache;
import org.springframework.security.providers.dao.cache.NullUserCache;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.cache.NullUserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import org.springframework.ws.soap.security.support.SpringSecurityUtils;
@@ -43,7 +43,7 @@ import org.springframework.ws.soap.security.support.SpringSecurityUtils;
* password contained in this details object is then compared with the digest in the message.
*
* @author Arjen Poutsma
* @see org.springframework.security.userdetails.UserDetailsService
* @see org.springframework.security.core.userdetails.UserDetailsService
* @see org.springframework.security.ui.digestauth.DigestProcessingFilter
* @since 1.5.0
*/
@@ -113,4 +113,4 @@ public class SpringDigestPasswordValidationCallbackHandler extends AbstractWsPas
}
return user;
}
}
}

View File

@@ -16,21 +16,20 @@
package org.springframework.ws.soap.security.wss4j.callback;
import java.io.IOException;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;
/**
* Callback handler that validates a certificate uses an Spring Security <code>AuthenticationManager</code>. Logic based
* on Spring Security's <code>BasicProcessingFilter</code>.
@@ -40,7 +39,7 @@ import org.springframework.ws.soap.security.callback.CleanupCallback;
* created with the username as principal and password as credentials.
*
* @author Arjen Poutsma
* @see org.springframework.security.providers.UsernamePasswordAuthenticationToken
* @see org.springframework.security.authentication.UsernamePasswordAuthenticationToken
* @see org.springframework.security.ui.basicauth.BasicProcessingFilter
* @since 1.5.0
*/
@@ -91,4 +90,4 @@ public class SpringPlainTextPasswordValidationCallbackHandler extends AbstractWs
}
}
}
}
}

View File

@@ -0,0 +1,131 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.security.x509;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.ws.soap.security.x509.cache.NullX509UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;
import java.security.cert.X509Certificate;
/**
* Processes an X.509 authentication request.
* <p>Migrated from Spring Security 2 since it has been removed in Spring Security 3.</p>
*
* @author Luke Taylor
* @version $Id: X509AuthenticationProvider.java 3256 2008-08-18 18:20:48Z luke_t $
*/
public class X509AuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(X509AuthenticationProvider.class);
//~ Instance fields ================================================================================================
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private X509AuthoritiesPopulator x509AuthoritiesPopulator;
private X509UserCache userCache = new NullX509UserCache();
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(userCache, "An x509UserCache must be set");
Assert.notNull(x509AuthoritiesPopulator, "An X509AuthoritiesPopulator must be set");
Assert.notNull(this.messages, "A message source must be set");
}
/**
* If the supplied authentication token contains a certificate then this will be passed to the configured
* {@link X509AuthoritiesPopulator} to obtain the user details and authorities for the user identified by the
* certificate.<p>If no certificate is present (for example, if the filter is applied to an HttpRequest for
* which client authentication hasn't been configured in the container) then a BadCredentialsException will be
* raised.</p>
*
* @param authentication the authentication request.
*
* @return an X509AuthenticationToken containing the authorities of the principal represented by the certificate.
*
* @throws AuthenticationException if the {@link X509AuthoritiesPopulator} rejects the certficate.
* @throws BadCredentialsException if no certificate was presented in the authentication request.
*/
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}
if (logger.isDebugEnabled()) {
logger.debug("X509 authentication request: " + authentication);
}
X509Certificate clientCertificate = (X509Certificate) authentication.getCredentials();
if (clientCertificate == null) {
throw new BadCredentialsException(messages.getMessage("X509AuthenticationProvider.certificateNull",
"Certificate is null"));
}
UserDetails user = userCache.getUserFromCache(clientCertificate);
if (user == null) {
if (logger.isDebugEnabled()) {
logger.debug("Authenticating with certificate " + clientCertificate);
}
user = x509AuthoritiesPopulator.getUserDetails(clientCertificate);
userCache.putUserInCache(clientCertificate, user);
}
X509AuthenticationToken result = new X509AuthenticationToken(user, clientCertificate, user.getAuthorities());
result.setDetails(authentication.getDetails());
return result;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
public void setX509AuthoritiesPopulator(X509AuthoritiesPopulator x509AuthoritiesPopulator) {
this.x509AuthoritiesPopulator = x509AuthoritiesPopulator;
}
public void setX509UserCache(X509UserCache cache) {
this.userCache = cache;
}
public boolean supports(Class authentication) {
return X509AuthenticationToken.class.isAssignableFrom(authentication);
}
}

View File

@@ -0,0 +1,78 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.security.x509;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import java.security.cert.X509Certificate;
import java.util.Collection;
/**
* <code>Authentication</code> implementation for X.509 client-certificate authentication.
* <p>Migrated from Spring Security 2 since it has been removed in Spring Security 3.</p>
*
* @author Luke Taylor
* @version $Id: X509AuthenticationToken.java 2544 2008-01-29 11:50:33Z luke_t $
*/
public class X509AuthenticationToken extends AbstractAuthenticationToken {
//~ Instance fields ================================================================================================
private static final long serialVersionUID = 1L;
private Object principal;
private X509Certificate credentials;
//~ Constructors ===================================================================================================
/**
* Used for an authentication request. The {@link org.springframework.security.core.Authentication#isAuthenticated()} will return
* <code>false</code>.
*
* @param credentials the certificate
*/
public X509AuthenticationToken(X509Certificate credentials) {
super(null);
this.credentials = credentials;
}
/**
* Used for an authentication response object. The {@link org.springframework.security.core.Authentication#isAuthenticated()}
* will return <code>true</code>.
*
* @param principal the principal, which is generally a
* <code>UserDetails</code>
* @param credentials the certificate
* @param authorities the authorities
*/
public X509AuthenticationToken(Object principal, X509Certificate credentials, Collection<GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(true);
}
//~ Methods ========================================================================================================
public Object getCredentials() {
return credentials;
}
public Object getPrincipal() {
return principal;
}
}

View File

@@ -0,0 +1,55 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.security.x509;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import java.security.cert.X509Certificate;
/**
* Populates the <code>UserDetails</code> associated with the X.509
* certificate presented by a client.
* <p>
* Although the certificate will already have been validated by the web container,
* implementations may choose to perform additional application-specific checks on
* the certificate content here. If an implementation chooses to reject the certificate,
* it should throw a {@link org.springframework.security.authentication.BadCredentialsException}.
* </p>
* <p>Migrated from Spring Security 2 since it has been removed in Spring Security 3.</p>
*
* @author Luke Taylor
* @version $Id: X509AuthoritiesPopulator.java 2544 2008-01-29 11:50:33Z luke_t $
*/
public interface X509AuthoritiesPopulator {
//~ Methods ========================================================================================================
/**
* Obtains the granted authorities for the specified user.<p>May throw any
* <code>AuthenticationException</code> or return <code>null</code> if the authorities are unavailable.</p>
*
* @param userCertificate the X.509 certificate supplied
*
* @return the details of the indicated user (at minimum the granted authorities and the username)
*
* @throws AuthenticationException if the user details are not available or the certificate isn't valid for the
* application's purpose.
*/
UserDetails getUserDetails(X509Certificate userCertificate)
throws AuthenticationException;
}

View File

@@ -0,0 +1,44 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.security.x509;
import org.springframework.security.core.userdetails.UserDetails;
import java.security.cert.X509Certificate;
/**
* Provides a cache of {@link UserDetails} objects for the
* {@link X509AuthenticationProvider}.
* <p>
* Similar in function to the {@link org.springframework.security.core.userdetails.UserCache}
* used by the Dao provider, but the cache is keyed with the user's certificate
* rather than the user name.
* </p>
* <p>Migrated from Spring Security 2 since it has been removed in Spring Security 3.</p>
*
* @author Luke Taylor
* @version $Id: X509UserCache.java 2544 2008-01-29 11:50:33Z luke_t $
*/
public interface X509UserCache {
//~ Methods ========================================================================================================
UserDetails getUserFromCache(X509Certificate userCertificate);
void putUserInCache(X509Certificate key, UserDetails user);
void removeUserFromCache(X509Certificate key);
}

View File

@@ -0,0 +1,109 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.security.x509.cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.Element;
import net.sf.ehcache.Ehcache;
import org.springframework.ws.soap.security.x509.X509UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.util.Assert;
import java.security.cert.X509Certificate;
/**
* Caches <code>User</code> objects using a Spring IoC defined <a
* href="http://ehcache.sourceforge.net">EHCACHE</a>.
* <p>Migrated from Spring Security 2 since it has been removed in Spring Security 3.</p>
*
* @author Luke Taylor
* @author Ben Alex
* @version $Id: EhCacheBasedX509UserCache.java 2544 2008-01-29 11:50:33Z luke_t $
*/
public class EhCacheBasedX509UserCache implements X509UserCache, InitializingBean {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(EhCacheBasedX509UserCache.class);
//~ Instance fields ================================================================================================
private Ehcache cache;
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "cache is mandatory");
}
public UserDetails getUserFromCache(X509Certificate userCert) {
Element element = null;
try {
element = cache.get(userCert);
} catch (CacheException cacheException) {
throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage());
}
if (logger.isDebugEnabled()) {
String subjectDN = "unknown";
if ((userCert != null) && (userCert.getSubjectDN() != null)) {
subjectDN = userCert.getSubjectDN().toString();
}
logger.debug("X.509 Cache hit. SubjectDN: " + subjectDN);
}
if (element == null) {
return null;
} else {
return (UserDetails) element.getValue();
}
}
public void putUserInCache(X509Certificate userCert, UserDetails user) {
Element element = new Element(userCert, user);
if (logger.isDebugEnabled()) {
logger.debug("Cache put: " + userCert.getSubjectDN());
}
cache.put(element);
}
public void removeUserFromCache(X509Certificate userCert) {
if (logger.isDebugEnabled()) {
logger.debug("Cache remove: " + userCert.getSubjectDN());
}
cache.remove(userCert);
}
public void setCache(Ehcache cache) {
this.cache = cache;
}
}

View File

@@ -0,0 +1,42 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.security.x509.cache;
import org.springframework.ws.soap.security.x509.X509UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import java.security.cert.X509Certificate;
/**
* "Cache" that doesn't do any caching.
* <p>Migrated from Spring Security 2 since it has been removed in Spring Security 3.</p>
*
* @author Luke Taylor
* @version $Id: NullX509UserCache.java 2544 2008-01-29 11:50:33Z luke_t $
*/
public class NullX509UserCache implements X509UserCache {
//~ Methods ========================================================================================================
public UserDetails getUserFromCache(X509Certificate certificate) {
return null;
}
public void putUserInCache(X509Certificate certificate, UserDetails user) {}
public void removeUserFromCache(X509Certificate certificate) {}
}

View File

@@ -0,0 +1,118 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.security.x509.populator;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.ws.soap.security.x509.X509AuthoritiesPopulator;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;
import java.security.cert.X509Certificate;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Populates the X509 authorities via an {@link org.springframework.security.core.userdetails.UserDetailsService}.
* <p>Migrated from Spring Security 2 since it has been removed in Spring Security 3.</p>
*
* @author Luke Taylor
* @version $Id: DaoX509AuthoritiesPopulator.java 2544 2008-01-29 11:50:33Z luke_t $
*/
public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator, InitializingBean, MessageSourceAware {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(DaoX509AuthoritiesPopulator.class);
//~ Instance fields ================================================================================================
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private Pattern subjectDNPattern;
private String subjectDNRegex = "CN=(.*?),";
private UserDetailsService userDetailsService;
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(userDetailsService, "An authenticationDao must be set");
Assert.notNull(this.messages, "A message source must be set");
subjectDNPattern = Pattern.compile(subjectDNRegex, Pattern.CASE_INSENSITIVE);
}
public UserDetails getUserDetails(X509Certificate clientCert) throws AuthenticationException {
String subjectDN = clientCert.getSubjectDN().getName();
Matcher matcher = subjectDNPattern.matcher(subjectDN);
if (!matcher.find()) {
throw new BadCredentialsException(messages.getMessage("DaoX509AuthoritiesPopulator.noMatching",
new Object[] {subjectDN}, "No matching pattern was found in subjectDN: {0}"));
}
if (matcher.groupCount() != 1) {
throw new IllegalArgumentException("Regular expression must contain a single group ");
}
String userName = matcher.group(1);
UserDetails user = this.userDetailsService.loadUserByUsername(userName);
if (user == null) {
throw new AuthenticationServiceException(
"UserDetailsService returned null, which is an interface contract violation");
}
return user;
}
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
/**
* Sets the regular expression which will by used to extract the user name from the certificate's Subject
* DN.
* <p>It should contain a single group; for example the default expression "CN=(.?)," matches the common
* name field. So "CN=Jimi Hendrix, OU=..." will give a user name of "Jimi Hendrix".</p>
* <p>The matches are case insensitive. So "emailAddress=(.?)," will match "EMAILADDRESS=jimi@hendrix.org,
* CN=..." giving a user name "jimi@hendrix.org"</p>
*
* @param subjectDNRegex the regular expression to find in the subject
*/
public void setSubjectDNRegex(String subjectDNRegex) {
this.subjectDNRegex = subjectDNRegex;
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
}

View File

@@ -24,11 +24,11 @@ import javax.security.auth.callback.UnsupportedCallbackException;
import com.sun.xml.wss.impl.callback.CertificateValidationCallback;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.x509.X509AuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ws.soap.security.x509.X509AuthenticationToken;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
import org.springframework.ws.soap.security.callback.CleanupCallback;
@@ -44,9 +44,8 @@ import org.springframework.ws.soap.security.callback.CleanupCallback;
* <code>UnsupportedCallbackException</code> for others.
*
* @author Arjen Poutsma
* @see org.springframework.security.providers.x509.X509AuthenticationToken
* @see org.springframework.security.providers.x509.X509AuthenticationProvider
* @see org.springframework.security.ui.x509.X509ProcessingFilter
* @see org.springframework.ws.soap.security.x509.X509AuthenticationToken
* @see org.springframework.ws.soap.security.x509.X509AuthenticationProvider
* @see com.sun.xml.wss.impl.callback.CertificateValidationCallback
* @since 1.5.0
*/
@@ -115,4 +114,4 @@ public class SpringCertificateValidationCallbackHandler extends AbstractCallback
return result;
}
}
}
}

View File

@@ -25,13 +25,13 @@ import com.sun.xml.wss.impl.callback.TimestampValidationCallback;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.dao.UserCache;
import org.springframework.security.providers.dao.cache.NullUserCache;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.cache.NullUserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
import org.springframework.ws.soap.security.callback.CleanupCallback;
@@ -48,10 +48,9 @@ import org.springframework.ws.soap.security.support.SpringSecurityUtils;
* and throws an <code>UnsupportedCallbackException</code> for others.
*
* @author Arjen Poutsma
* @see org.springframework.security.userdetails.UserDetailsService
* @see org.springframework.security.core.userdetails.UserDetailsService
* @see com.sun.xml.wss.impl.callback.PasswordValidationCallback
* @see com.sun.xml.wss.impl.callback.PasswordValidationCallback.DigestPasswordRequest
* @see org.springframework.security.ui.digestauth.DigestProcessingFilter
* @since 1.5.0
*/
public class SpringDigestPasswordValidationCallbackHandler extends AbstractCallbackHandler implements InitializingBean {
@@ -156,4 +155,4 @@ public class SpringDigestPasswordValidationCallbackHandler extends AbstractCallb
}
}
}
}

View File

@@ -23,11 +23,11 @@ import javax.security.auth.callback.UnsupportedCallbackException;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
import org.springframework.ws.soap.security.callback.CleanupCallback;
@@ -44,10 +44,9 @@ import org.springframework.ws.soap.security.callback.CleanupCallback;
* <code>PlainTextPasswordRequest</code>, and throws an <code>UnsupportedCallbackException</code> for others.
*
* @author Arjen Poutsma
* @see org.springframework.security.providers.UsernamePasswordAuthenticationToken
* @see org.springframework.security.authentication.UsernamePasswordAuthenticationToken
* @see com.sun.xml.wss.impl.callback.PasswordValidationCallback
* @see com.sun.xml.wss.impl.callback.PasswordValidationCallback.PlainTextPasswordRequest
* @see org.springframework.security.ui.basicauth.BasicProcessingFilter
* @since 1.5.0
*/
public class SpringPlainTextPasswordValidationCallbackHandler extends AbstractCallbackHandler
@@ -119,4 +118,4 @@ public class SpringPlainTextPasswordValidationCallbackHandler extends AbstractCa
}
}
}
}

View File

@@ -23,13 +23,13 @@ import javax.security.auth.callback.UnsupportedCallbackException;
import com.sun.xml.wss.impl.callback.PasswordCallback;
import com.sun.xml.wss.impl.callback.UsernameCallback;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
/**
* Callback handler that adds username/password information to a mesage using an Spring Security {@link
* org.springframework.security.context.SecurityContext}.
* org.springframework.security.core.context.SecurityContext}.
* <p/>
* This class handles <code>UsernameCallback</code>s and <code>PasswordCallback</code>s, and throws an
* <code>UnsupportedCallbackException</code> for others
@@ -67,4 +67,4 @@ public class SpringUsernamePasswordCallbackHandler extends AbstractCallbackHandl
}
throw new UnsupportedCallbackException(callback);
}
}
}

View File

@@ -18,13 +18,13 @@ package org.springframework.ws.soap.security.wss4j;
import java.util.Properties;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.userdetails.memory.InMemoryDaoImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
@@ -128,4 +128,4 @@ public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCa
replay(authenticationManager);
return interceptor;
}
}
}

View File

@@ -16,14 +16,16 @@
package org.springframework.ws.soap.security.wss4j.callback;
import org.springframework.security.Authentication;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import java.util.Collection;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.junit.Assert;
@@ -68,10 +70,10 @@ public class SpringDigestPasswordValidationCallbackHandlerTest {
Assert.assertNotNull("SecurityContext must not be null", context);
Authentication authentication = context.getAuthentication();
Assert.assertNotNull("Authentication must not be null", authentication);
GrantedAuthority[] authorities = authentication.getAuthorities();
Collection<GrantedAuthority> authorities = authentication.getAuthorities();
Assert.assertTrue("GrantedAuthority[] must not be null or empty",
(authorities != null && authorities.length > 0));
Assert.assertEquals("Unexpected authority", grantedAuthority, authorities[0]);
(authorities != null && authorities.size() > 0));
Assert.assertEquals("Unexpected authority", grantedAuthority, authorities.iterator().next());
verify(userDetailsService);
}

View File

@@ -21,12 +21,12 @@ import java.security.KeyStore;
import java.security.cert.X509Certificate;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.providers.x509.X509AuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.ws.soap.security.x509.X509AuthenticationToken;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import com.sun.xml.wss.impl.callback.CertificateValidationCallback;
@@ -113,4 +113,4 @@ public class SpringCertificateValidationCallbackHandlerTest {
Assert.assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication());
}
}
}

View File

@@ -16,13 +16,13 @@
package org.springframework.ws.soap.security.xwss.callback;
import org.springframework.security.DisabledException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
@@ -136,4 +136,4 @@ public class SpringDigestPasswordValidationCallbackHandlerTest {
Assert.assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication());
}
}
}

View File

@@ -16,13 +16,13 @@
package org.springframework.ws.soap.security.xwss.callback;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
@@ -102,4 +102,4 @@ public class SpringPlainTextPasswordValidationCallbackHandlerTest {
Assert.assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication());
}
}
}

View File

@@ -16,9 +16,9 @@
package org.springframework.ws.soap.security.xwss.callback;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import com.sun.xml.wss.impl.callback.PasswordCallback;
import com.sun.xml.wss.impl.callback.UsernameCallback;
@@ -56,4 +56,4 @@ public class SpringUsernamePasswordCallbackHandlerTest {
handler.handleInternal(passwordCallback);
Assert.assertEquals("Invalid username", "Ernie", passwordCallback.getPassword());
}
}
}

View File

@@ -9,11 +9,13 @@ Import-Template:
javax.security.auth.*;version="0",
javax.xml.namespace.*;version="0",
javax.xml.soap.*;version="[1.1.0, 2.0.0)";resolution:=optional,
net.sf.ehcache.*;version="2.0.0";resolution:=optional,
org.apache.axiom.*;version="[1.2.5, 2.0.0)";resolution:=optional,
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.apache.ws.security.*;version="[1.5.8, 2.0.0)";resolution:=optional,
org.apache.xml.security.*;version="[1.0.5.D2, 2.0.0)";resolution:=optional,
org.springframework.beans.*;version=${spring.framework.osgi.range},
org.springframework.context.*;version=${spring.framework.osgi.range},
org.springframework.core.*;version=${spring.framework.osgi.range},
org.springframework.dao.*;version=${spring.framework.osgi.range},
org.springframework.security.*;version="[2.0.0, 3.0.0)",

View File

@@ -749,9 +749,9 @@
<bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<bean class="org.springframework.security.providers.x509.X509AuthenticationProvider">
<bean class="org.springframework.ws.soap.security.x509.X509AuthenticationProvider">
<property name="x509AuthoritiesPopulator">
<bean class="org.springframework.security.providers.x509.populator.DaoX509AuthoritiesPopulator">
<bean class="org.springframework.ws.soap.security.x509.populator.DaoX509AuthoritiesPopulator">
<property name="userDetailsService" ref="userDetailsService"/>
</bean>
</property>