'Spring security with password encoding and salting
I am trying to to authenticate user with spring-security with SHA hashing and salting. I have added extra field in users table for extra salt and customize UserDetails with this salt but whenever I try to login it is throwing bad credential exception.
My CustomJdbcDaoImpl class is :
public class CustomJdbcDaoImpl extends JdbcDaoImpl implements IChangePassword {
private Logger logger = LoggerFactory.getLogger(CustomJdbcDaoImpl.class);
@Override
protected UserDetails createUserDetails(String username,UserDetails userFromUserQuery,
List<GrantedAuthority> combinedAuthorities){
String returnUsername = userFromUserQuery.getUsername();
if(!isUsernameBasedPrimaryKey()){
returnUsername = username;
}
logger.info("inside @class CustomJdbcDaoImpl @method createUserDetails USER DETAILS ARE: "+userFromUserQuery.getPassword()+"authritieds: "+combinedAuthorities);
return new SaltedUser(returnUsername,
userFromUserQuery.getPassword(),
userFromUserQuery.isEnabled(),
true,
true,
true,
combinedAuthorities,
((SaltedUser)userFromUserQuery).getSalt());
}
@Override
protected List<UserDetails> loadUsersByUsername(String username) {
return getJdbcTemplate()
.query(getUsersByUsernameQuery(),
new String[] {username},
new RowMapper<UserDetails>() {
public SaltedUser mapRow(ResultSet rs, int rowNum) throws SQLException {
String username = rs.getString(1);
String password = rs.getString(2);
boolean enabled = rs.getBoolean(3);
String salt = rs.getString(4);
SaltedUser saltedUser = new SaltedUser(username, password, enabled,
true,
true,
true,
AuthorityUtils.NO_AUTHORITIES,
salt);
logger.info("inside @class @method loadUsersByUsername salted password is: "+saltedUser.getPassword());
return saltedUser;
}
});
}
@Override
public void changePassword(String username, String password) {
getJdbcTemplate().
update("update users set password = ? where username = ?",password,username);
}
}
for changing password each time with salt my DatabasePasswordSecurerBean class is
public class DatabasePasswordSecurerBean extends JdbcDaoSupport {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private SaltSource saltSource;
@Autowired
private UserDetailsService userDetailsService;
private Logger logger = LoggerFactory.getLogger(DatabasePasswordSecurerBean.class);
public void secureDatabase(){
logger.info("inside @class DatabasePasswordSecurerBean @method secureDatabase entry...");
getJdbcTemplate().query("select username,password from users",new RowCallbackHandler(){
@Override
public void processRow(ResultSet rs) throws SQLException {
String username = rs.getString(1);
String password = rs.getString(2);
UserDetails user = userDetailsService.loadUserByUsername(username);
String encodedPassword = passwordEncoder.encodePassword(password,saltSource.getSalt(user));
getJdbcTemplate().update("update users set password = ? where username = ?",
encodedPassword,username);
logger.info("@class DatabasePasswordSecurerBean @method secureDatabase updating password for user: "+username + "to: "+encodedPassword);
}
});
}
}
security.xml configurations are
<http auto-config="true">
<intercept-url pattern="/*" access="ROLE_USER" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="jdbcUserService">
<password-encoder ref="passwordEncoder" >
<salt-source ref="saltSource" />
</password-encoder>
</authentication-provider>
</authentication-manager>
</beans:beans>
and my application.xml is
<!-- Simple implementation of the standard JDBC DataSource interface,
configuring the plain old JDBC DriverManager via bean properties -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driverClassName}" />
<property name="url" value="${db.connection.url}" />
<property name="username" value="${db.connection.username}" />
<property name="password" value="${db.connection.password}" />
</bean>
<bean id="jdbcUserService" class="com.petCart.springsecurity.security.CustomJdbcDaoImpl">
<property name="dataSource" ref="dataSource" />
<property name="enableGroups" value="true"></property>
<property name="enableAuthorities" value="false"></property>
<property name="usersByUsernameQuery">
<value>
select username,password,enabled,salt from users where username = ?
</value>
</property>
<property name="groupAuthoritiesByUsernameQuery">
<value>
select r.roleid,r.role_name,p.permissionname from roles r
join userrole ur on ur.roleid = r.roleid
join users u on u.id = ur.userid
join rolepermission rp on r.roleid = rp.roleid
join permissions p on p.permissionid = rp.permissionid
where u.username = ?
</value>
</property>
</bean>
<!-- password encoder -->
<bean class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" id="passwordEncoder"/>
<bean class="com.petCart.springsecurity.security.DatabasePasswordSecurerBean" init-method="secureDatabase" depends-on="dataSource">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
<property name="userPropertyToUse" value="username" />
</bean>
Solution 1:[1]
Try to change from
<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
<property name="userPropertyToUse" value="username" />
</bean>
to
<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
<property name="userPropertyToUse" value="salt" />
</bean>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | user2669657 |
