【发布时间】:2016-04-06 04:30:32
【问题描述】:
我正在尝试使用 SHA 散列和加盐对具有 spring-security 的用户进行身份验证。我在用户表中添加了额外的字段以获取额外的盐,并使用此盐自定义 UserDetails,但每当我尝试登录时,它都会引发错误的凭据异常。
我的CustomJdbcDaoImpl 班级是:
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);
}
}
每次用盐更改密码我的DatabasePasswordSecurerBean 类是
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>
我的 application.xml 是
<!-- 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>
【问题讨论】:
-
我真的把我的假期和所有这些东西混为一谈,请有人帮助我......
-
可能不是您期望的答案,但是您为什么不使用 Spring Security 已经提供的 BCrypt 呢?它比SHA强,还包含salt,一切由你管理,你只需要调用密码编码器。
标签: spring spring-security salt