mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-26 13:53:14 +00:00
initial cut at allowing pluggable digest strategy for use in password handling in DaoAuthenticationProvider
This commit is contained in:
parent
547b1ff4e3
commit
aed9d2a1d8
@ -46,6 +46,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|||||||
//~ Instance fields ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
private AuthenticationDao authenticationDao;
|
private AuthenticationDao authenticationDao;
|
||||||
|
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
||||||
private boolean ignorePasswordCase = false;
|
private boolean ignorePasswordCase = false;
|
||||||
private boolean ignoreUsernameCase = true;
|
private boolean ignoreUsernameCase = true;
|
||||||
|
|
||||||
@ -89,6 +90,21 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|||||||
return ignoreUsernameCase;
|
return ignoreUsernameCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the PasswordEncoder instance to be used to encode and validate
|
||||||
|
* passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
|
||||||
|
* default.
|
||||||
|
*
|
||||||
|
* @param passwordEncoder The passwordEncoder to use
|
||||||
|
*/
|
||||||
|
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PasswordEncoder getPasswordEncoder() {
|
||||||
|
return passwordEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
if (this.authenticationDao == null) {
|
if (this.authenticationDao == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@ -116,15 +132,9 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|||||||
throw new BadCredentialsException("Bad credentials presented");
|
throw new BadCredentialsException("Bad credentials presented");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.getPassword().toLowerCase().equals(authentication.getCredentials()
|
if (!passwordEncoder.isPasswordValid(user.getPassword(),
|
||||||
.toString()
|
authentication.getCredentials().toString(), user,
|
||||||
.toLowerCase())) {
|
ignorePasswordCase)) {
|
||||||
throw new BadCredentialsException("Bad credentials presented");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!this.ignorePasswordCase)
|
|
||||||
&& (!user.getPassword().equals(authentication.getCredentials()
|
|
||||||
.toString()))) {
|
|
||||||
throw new BadCredentialsException("Bad credentials presented");
|
throw new BadCredentialsException("Bad credentials presented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +143,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new UsernamePasswordAuthenticationToken(user.getUsername(),
|
return new UsernamePasswordAuthenticationToken(user.getUsername(),
|
||||||
user.getPassword(), user.getAuthorities());
|
authentication.getCredentials().toString(), user.getAuthorities());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supports(Class authentication) {
|
public boolean supports(Class authentication) {
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
/* Copyright 2004 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 net.sf.acegisecurity.providers.dao;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* MD5 implementation of PasswordEncoder.<br/
|
||||||
|
* > The ignorePasswordCase parameter is not used for this implementation.<br/
|
||||||
|
* > A null password is encoded to the same value as an empty ("") password.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author colin sampaleanu
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class MD5PasswordEncoder implements PasswordEncoder {
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(net.sf.acegisecurity.providers.dao.User, java.lang.String, boolean)
|
||||||
|
*/
|
||||||
|
public boolean isPasswordValid(String encPass, String rawPass,
|
||||||
|
Object saltSource, boolean ignorePasswordCase) {
|
||||||
|
String pass1 = "" + encPass;
|
||||||
|
String pass2 = DigestUtils.md5Hex("" + rawPass);
|
||||||
|
|
||||||
|
return pass1.equals(pass2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.sf.acegisecurity.providers.dao.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
|
||||||
|
*/
|
||||||
|
public String encodePassword(String rawPass, Object saltSource) {
|
||||||
|
return DigestUtils.md5Hex("" + rawPass);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/* Copyright 2004 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 net.sf.acegisecurity.providers.dao;
|
||||||
|
|
||||||
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Describes authentication operations on a password, so that digest algorithms
|
||||||
|
* can be abstracted
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author colin sampaleanu
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface PasswordEncoder {
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public boolean isPasswordValid(String encPass, String rawPass,
|
||||||
|
Object saltSource, boolean ignorePasswordCase)
|
||||||
|
throws DataAccessException;
|
||||||
|
|
||||||
|
public String encodePassword(String rawPass, Object saltSource);
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/* Copyright 2004 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 net.sf.acegisecurity.providers.dao;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Plaintext implementation of PasswordEncoder.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author colin sampaleanu
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class PlaintextPasswordEncoder implements PasswordEncoder {
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(net.sf.acegisecurity.providers.dao.User, java.lang.String, boolean)
|
||||||
|
*/
|
||||||
|
public boolean isPasswordValid(String encPass, String rawPass,
|
||||||
|
Object saltSource, boolean ignorePasswordCase) {
|
||||||
|
String pass1 = "" + encPass;
|
||||||
|
String pass2 = "" + rawPass;
|
||||||
|
|
||||||
|
if (!ignorePasswordCase) {
|
||||||
|
return pass1.equals(pass2);
|
||||||
|
} else {
|
||||||
|
return pass1.equalsIgnoreCase(pass2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.sf.acegisecurity.providers.dao.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
|
||||||
|
*/
|
||||||
|
public String encodePassword(String rawPass, Object saltSource) {
|
||||||
|
return rawPass;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/* Copyright 2004 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 net.sf.acegisecurity.providers.dao;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SHA implementation of PasswordEncoder.<br/
|
||||||
|
* > The ignorePasswordCase parameter is not used for this implementation.<br/
|
||||||
|
* > A null password is encoded to the same value as an empty ("") password.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author colin sampaleanu
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class SHAPasswordEncoder implements PasswordEncoder {
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.sf.acegisecurity.providers.dao.PasswordEncoder#isPasswordValid(net.sf.acegisecurity.providers.dao.User, java.lang.String, boolean)
|
||||||
|
*/
|
||||||
|
public boolean isPasswordValid(String encPass, String rawPass,
|
||||||
|
Object saltSource, boolean ignorePasswordCase) {
|
||||||
|
String pass1 = "" + encPass;
|
||||||
|
String pass2 = DigestUtils.shaHex("" + rawPass);
|
||||||
|
|
||||||
|
return pass1.equals(pass2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.sf.acegisecurity.providers.dao.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
|
||||||
|
*/
|
||||||
|
public String encodePassword(String rawPass, Object saltSource) {
|
||||||
|
return DigestUtils.shaHex("" + rawPass);
|
||||||
|
}
|
||||||
|
}
|
@ -48,11 +48,14 @@ import javax.sql.DataSource;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* A default database structure is assumed, which most users of this class will
|
* A default database structure is assumed, (see {@link
|
||||||
|
* #DEF_USERS_BY_USERNAME_QUERY} and {@link
|
||||||
|
* #DEF_AUTHORITIES_BY_USERNAME_QUERY}, which most users of this class will
|
||||||
* need to override, if using an existing scheme. This may be done by setting
|
* need to override, if using an existing scheme. This may be done by setting
|
||||||
* the default query strings used, or if that does not provide enough
|
* the default query strings used. If this does not provide enough
|
||||||
* flexibility, setting the actual {@link MappingSqlQuery} instances used to
|
* flexibility, another strategy would be to subclass this class and override
|
||||||
* query the database.
|
* the {@link MappingSqlQuery} instances used, via the {@link
|
||||||
|
* #initMappingSqlQueries()} extension point.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
@ -68,10 +71,11 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao {
|
|||||||
|
|
||||||
//~ Instance fields ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
protected MappingSqlQuery authoritiesByUsernameMapping;
|
private MappingSqlQuery authoritiesByUsernameMapping;
|
||||||
protected MappingSqlQuery usersByUsernameMapping;
|
private MappingSqlQuery usersByUsernameMapping;
|
||||||
protected String authoritiesByUsernameQuery;
|
private String authoritiesByUsernameQuery;
|
||||||
protected String usersByUsernameQuery;
|
private String rolePrefix = "ROLE_";
|
||||||
|
private String usersByUsernameQuery;
|
||||||
|
|
||||||
//~ Constructors ===========================================================
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
@ -82,16 +86,6 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao {
|
|||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the default MappingSqlQuery used for retrieving authorities by
|
|
||||||
* username to be overriden. This may be used when overriding the query
|
|
||||||
* string alone is inadequate. Note that there is no point in setting this
|
|
||||||
* property and also specifying a query string, since there will be no
|
|
||||||
* way for the instance set by this property to get at the query string.
|
|
||||||
* As such, the MappingSqlQuery should be self contained.
|
|
||||||
*
|
|
||||||
* @param authoritiesByUsernameQuery The authoritiesByUsernameQuery to set.
|
|
||||||
*/
|
|
||||||
public void setAuthoritiesByUsernameMapping(
|
public void setAuthoritiesByUsernameMapping(
|
||||||
MappingSqlQuery authoritiesByUsernameQuery) {
|
MappingSqlQuery authoritiesByUsernameQuery) {
|
||||||
this.authoritiesByUsernameMapping = authoritiesByUsernameQuery;
|
this.authoritiesByUsernameMapping = authoritiesByUsernameQuery;
|
||||||
@ -120,15 +114,23 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows the default MappingSqlQuery used for retrieving users by username
|
* Allows a default role prefix to be specified. If this is set to a
|
||||||
* to be overriden. This may be used when overriding the query string
|
* non-empty value, then it is automatically prepended to any roles read
|
||||||
* alone is inadequate. Note that there is no point in setting this
|
* in from the db. This may for example be used to add the
|
||||||
* property and also specifying a query string, since there will be no
|
* <code>ROLE_</code> prefix expected to exist in role names (by default)
|
||||||
* way for the instance set by this property to get at the query string.
|
* by some other Acegi Security framework classes, in the case that the
|
||||||
* As such, the MappingSqlQuery should be self contained.
|
* prefix is not already present in the db.
|
||||||
*
|
*
|
||||||
* @param usersByUsernameQuery The MappingSqlQuery to set.
|
* @param rolePrefix the new prefix
|
||||||
*/
|
*/
|
||||||
|
public void setRolePrefix(String rolePrefix) {
|
||||||
|
this.rolePrefix = rolePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRolePrefix() {
|
||||||
|
return rolePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
public void setUsersByUsernameMapping(MappingSqlQuery usersByUsernameQuery) {
|
public void setUsersByUsernameMapping(MappingSqlQuery usersByUsernameQuery) {
|
||||||
this.usersByUsernameMapping = usersByUsernameQuery;
|
this.usersByUsernameMapping = usersByUsernameQuery;
|
||||||
}
|
}
|
||||||
@ -183,8 +185,17 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void initDao() throws ApplicationContextException {
|
protected void initDao() throws ApplicationContextException {
|
||||||
usersByUsernameMapping = new UsersByUsernameMapping(getDataSource());
|
initMappingSqlQueries();
|
||||||
authoritiesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource());
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension point to allow other MappingSqlQuery objects to be substituted
|
||||||
|
* in a subclass
|
||||||
|
*/
|
||||||
|
protected void initMappingSqlQueries() {
|
||||||
|
setUsersByUsernameMapping(new UsersByUsernameMapping(getDataSource()));
|
||||||
|
setAuthoritiesByUsernameMapping(new AuthoritiesByUsernameMapping(
|
||||||
|
getDataSource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ Inner Classes ==========================================================
|
//~ Inner Classes ==========================================================
|
||||||
@ -201,8 +212,8 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao {
|
|||||||
|
|
||||||
protected Object mapRow(ResultSet rs, int rownum)
|
protected Object mapRow(ResultSet rs, int rownum)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
GrantedAuthorityImpl authority = new GrantedAuthorityImpl(rs
|
String roleName = rolePrefix + rs.getString(1);
|
||||||
.getString("authority"));
|
GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
|
||||||
|
|
||||||
return authority;
|
return authority;
|
||||||
}
|
}
|
||||||
@ -220,9 +231,9 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao {
|
|||||||
|
|
||||||
protected Object mapRow(ResultSet rs, int rownum)
|
protected Object mapRow(ResultSet rs, int rownum)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
String username = rs.getString("username");
|
String username = rs.getString(1);
|
||||||
String password = rs.getString("password");
|
String password = rs.getString(2);
|
||||||
boolean enabled = rs.getBoolean("enabled");
|
boolean enabled = rs.getBoolean(3);
|
||||||
User user = new User(username, password, enabled,
|
User user = new User(username, password, enabled,
|
||||||
new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")});
|
new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user