Created
July 5, 2011 13:32
-
-
Save asoftwareguy/1064840 to your computer and use it in GitHub Desktop.
Blog - Spring Security 2.x with multiple credentials
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.multicred; | |
import java.util.List; | |
import javax.servlet.http.HttpServletRequest; | |
import org.springframework.security.Authentication; | |
import org.springframework.security.AuthenticationException; | |
import org.springframework.security.BadCredentialsException; | |
import org.springframework.security.ui.AbstractProcessingFilter; | |
import org.springframework.security.ui.FilterChainOrder; | |
import org.springframework.util.Assert; | |
public class MultipleCredentialAuthenticationFilter extends AbstractProcessingFilter { | |
private String principalParameter; | |
private List credentialParameters; | |
@Override | |
public Authentication attemptAuthentication(HttpServletRequest _request) throws AuthenticationException { | |
String principal = obtainPrincipal(_request); | |
MultipleCredentials credentials = obtainCredentials(_request); | |
if (principal == null) { | |
principal = ""; | |
} | |
principal = principal.trim(); | |
if (principal.isEmpty()) { | |
throw new BadCredentialsException("Invalid Credentials"); | |
} | |
MultipleCredentialAuthenticationToken authRequest = new MultipleCredentialAuthenticationToken(principal, credentials); | |
// Allow subclasses to set the "details" property | |
setDetails(_request, authRequest); | |
return this.getAuthenticationManager().authenticate(authRequest); | |
} | |
private String obtainPrincipal(HttpServletRequest request) { | |
Assert.notNull(principalParameter, "principalParameter must be defined!"); | |
return request.getParameter(principalParameter); | |
} | |
private MultipleCredentials obtainCredentials(HttpServletRequest request) { | |
Assert.notNull(credentialParameters, "credentialParameters must be defined!"); | |
MultipleCredentials multipleCredentials = new MultipleCredentials(); | |
for (String credentialParameter : credentialParameters) { | |
multipleCredentials.add(credentialParameter, request.getParameter(credentialParameter)); | |
} | |
return multipleCredentials; | |
} | |
protected void setDetails(HttpServletRequest request, MultipleCredentialAuthenticationToken authRequest) { | |
authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); | |
} | |
public int getOrder() { | |
return FilterChainOrder.AUTHENTICATION_PROCESSING_FILTER; | |
} | |
@Override | |
public String getDefaultFilterProcessesUrl() { | |
return "/multi_security_check"; | |
} | |
public void setPrincipalParameter(String principalParameter) { | |
this.principalParameter = principalParameter; | |
} | |
public void setCredentialParameters(List credentialParameters) { | |
this.credentialParameters = credentialParameters; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.multicred; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Set; | |
import org.springframework.security.Authentication; | |
import org.springframework.security.AuthenticationException; | |
import org.springframework.security.BadCredentialsException; | |
import org.springframework.security.GrantedAuthority; | |
import org.springframework.security.providers.AuthenticationProvider; | |
/** | |
* This is an {@link AuthenticationProvider} that uses multiple credentials to | |
* authenticate the user. Authorities can be granted by supplying a | |
* {@link AuthorityGranter} function. | |
* | |
* | |
*/ | |
public class MultipleCredentialAuthenticationProvider implements AuthenticationProvider { | |
private MultipleCredentialAuthenticationService multipleCredentialAuthenticationService; | |
private List<AuthorityGranter> authorityGranters; | |
public Authentication authenticate(Authentication _authentication) throws AuthenticationException { | |
MultipleCredentialAuthenticationToken attemptAuthenticationToken = (MultipleCredentialAuthenticationToken) _authentication; | |
MultipleCredentialAuthenticationToken resultAuthenticationToken = null; | |
boolean authenticated = multipleCredentialAuthenticationService.authenticate((String) attemptAuthenticationToken.getPrincipal(), (MultipleCredentials) attemptAuthenticationToken.getCredentials()); | |
if (authenticated) { | |
GrantedAuthority[] grantedAuthorities = createGrantedAuthorityArray(attemptAuthenticationToken); | |
resultAuthenticationToken = new MultipleCredentialAuthenticationToken((String) attemptAuthenticationToken.getPrincipal(), (MultipleCredentials) attemptAuthenticationToken.getCredentials(), grantedAuthorities); | |
} else { | |
throw new BadCredentialsException("Bad Credentials"); | |
} | |
return resultAuthenticationToken; | |
} | |
/** | |
* Create the {@link GrantedAuthority} array, using any registered | |
* {@link AuthorityGranter}. | |
* | |
* @return a {@link GrantedAuthority} array; will be empty if no authorities | |
* have been granted | |
*/ | |
private GrantedAuthority[] createGrantedAuthorityArray(MultipleCredentialAuthenticationToken _multipleCredentialAuthenticationToken) throws AuthorityGranterUndefinedException { | |
GrantedAuthority[] grantedAuthorityArray = null; | |
Set grantedAuthoritySet = new HashSet(); | |
if (authorityGranters != null) { | |
for (AuthorityGranter authorityGranter : authorityGranters) { | |
grantedAuthoritySet.addAll(authorityGranter.grantAuthorities(_multipleCredentialAuthenticationToken)); | |
} | |
} else { | |
throw new AuthorityGranterUndefinedException(); | |
} | |
if (!grantedAuthoritySet.isEmpty()) { | |
grantedAuthorityArray = grantedAuthoritySet.toArray(new GrantedAuthority[grantedAuthoritySet.size()]); | |
} | |
return grantedAuthorityArray; | |
} | |
public boolean supports(Class _clazz) { | |
return MultipleCredentialAuthenticationToken.class.isAssignableFrom(_clazz); | |
} | |
public void setMultipleCredentialAuthenticationService(MultipleCredentialAuthenticationService multipleCredentialAuthenticationService) { | |
this.multipleCredentialAuthenticationService = multipleCredentialAuthenticationService; | |
} | |
public void setAuthorityGranters(List authorityGranters) { | |
this.authorityGranters = authorityGranters; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.multicred; | |
/** | |
* Multiple credential authentication service interface. | |
* | |
*/ | |
public interface MultipleCredentialAuthenticationService { | |
/** | |
* Authenticate using the provided principal and credentials. | |
* | |
* @param _principal | |
* the principal to use to authenticate | |
* @param _credentials | |
* the credentials to use to authenticate | |
* @return <code>true</code> iff authentication is successful, | |
* <code>false</code> otherwise | |
*/ | |
public boolean authenticate(String _principal, MultipleCredentials _credentials); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.multicred.impl; | |
import java.io.IOException; | |
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import javax.xml.rpc.ServiceException; | |
import example.multicred.MultipleCredentialAuthenticationService; | |
import example.multicred.MultipleCredentials; | |
public class MultipleCredentialAuthenticationServiceImpl implements MultipleCredentialAuthenticationService { | |
public boolean authenticate(String _principal, MultipleCredentials _credentials) { | |
String prin1 = _principal; | |
String cred1 = _credentials.getCredential("j_cred1"); | |
String cred2 = _credentials.getCredential("j_cred2"); | |
String cred3 = _credentials.getCredential("j_cred3"); | |
// do something to authenticate | |
// ... | |
return authenticated; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.multicred; | |
import org.springframework.security.GrantedAuthority; | |
import org.springframework.security.providers.AbstractAuthenticationToken; | |
public class MultipleCredentialAuthenticationToken extends AbstractAuthenticationToken { | |
private static final long serialVersionUID = 1L; | |
private String principal; | |
private MultipleCredentials credentials; | |
/** | |
* This constructor can be safely used by any code that wishes to create a | |
* <code>MultipleCredentialAuthenticationToken</code>, as the | |
* {@link #isAuthenticated()} will return <code>false</code>. | |
* | |
*/ | |
public MultipleCredentialAuthenticationToken(String _principal, MultipleCredentials _credentials) { | |
super(null); | |
this.principal = _principal; | |
this.credentials = _credentials; | |
setAuthenticated(false); | |
} | |
/** | |
* This constructor should only be used by <code>AuthenticationManager</code> | |
* or <code>AuthenticationProvider</code> implementations that are satisfied | |
* with producing a trusted (ie {@link #isAuthenticated()} = <code>true</code> | |
* ) authentication token. | |
* | |
*/ | |
public MultipleCredentialAuthenticationToken(String _principal, MultipleCredentials _credentials, GrantedAuthority[] _authorities) { | |
super(_authorities); | |
this.principal = _principal; | |
this.credentials = _credentials; | |
super.setAuthenticated(true); // must use super, as we override | |
} | |
public Object getCredentials() { | |
return this.credentials; | |
} | |
public Object getPrincipal() { | |
return this.principal; | |
} | |
@Override | |
public void setAuthenticated(boolean _isAuthenticated) throws IllegalArgumentException { | |
if (_isAuthenticated) { | |
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor containing GrantedAuthority[]s instead"); | |
} | |
super.setAuthenticated(false); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.multicred; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.Map; | |
/** | |
* Model object for storing multiple credentials. | |
* | |
*/ | |
public class MultipleCredentials { | |
private Map<String, String> credentials = new HashMap<String, String>(); | |
public void add(String _credentialName, String _credentialValue) { | |
if (_credentialName != null && !_credentialName.isEmpty() && _credentialValue != null && !_credentialValue.isEmpty()) { | |
credentials.put(_credentialName, _credentialValue); | |
} | |
} | |
public String getCredential(String _credentialName) { | |
String returnValue = null; | |
if (_credentialName != null && !_credentialName.isEmpty()) { | |
returnValue = credentials.get(_credentialName); | |
} | |
return returnValue; | |
} | |
public Map getCredentials() { | |
return Collections.unmodifiableMap(credentials); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<beans xmlns="http://www.springframework.org/schema/beans" | |
xmlns:security="http://www.springframework.org/schema/security" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" | |
xsi:schemaLocation=" | |
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd | |
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd | |
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> | |
<security:http auto-config="false" access-denied-page="/login.htm?msg=access_denied" | |
entry-point-ref="authenticationEntryPoint" | |
session-fixation-protection="newSession"> | |
<security:intercept-url pattern="/login.htm" | |
filters="none" /> | |
<security:intercept-url pattern="/**.htm" | |
access="ROLE_USER" /> | |
<security:logout logout-url="/logout" | |
logout-success-url="/login.htm?msg=logout_success" | |
invalidate-session="true" /> | |
</security:http> | |
<security:authentication-manager alias="authenticationManager" /> | |
<bean id="multipleCredentialAuthenticationFilter" | |
class="example.multicred.MultipleCredentialAuthenticationFilter"> | |
<security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" /> | |
<property name="authenticationManager" ref="authenticationManager" /> | |
<property name="defaultTargetUrl" value="/home.htm" /> | |
<property name="authenticationFailureUrl" value="/login.htm?msg=auth_failure" /> | |
<property name="filterProcessesUrl" value="/multi_security_check" /> | |
<property name="alwaysUseDefaultTargetUrl" value="true" /> | |
<property name="principalParameter" value="j_prin" /> | |
<property name="credentialParameters"> | |
<util:list> | |
<value>j_cred1</value> | |
<value>j_cred2</value> | |
<value>j_cred3</value> | |
</util:list> | |
</property> | |
</bean> | |
<bean id="authenticationEntryPoint" | |
class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint"> | |
<property name="loginFormUrl" value="/login.htm" /> | |
<property name="forceHttps" value="false" /> | |
</bean> | |
<bean id="multipleCredentialAuthenticationProvider" | |
class="example.multicred.MultipleCredentialAuthenticationProvider"> | |
<security:custom-authentication-provider /> | |
<property name="multipleCredentialAuthenticationService" ref="multipleCredentialAuthenticationService" /> | |
<property name="authorityGranters"> | |
<util:list> | |
<ref bean="roleUserAuthorityGranter" /> | |
</util:list> | |
</property> | |
</bean> | |
<bean id="multipleCredentialAuthenticationService" | |
class="example.multicred.impl.MultipleCredentialAuthenticationServiceImpl" /> | |
<bean id="roleUserAuthorityGranter" class="example.multicred.impl.RoleUserAuthorityGranterImpl" /> | |
</beans> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment