我必须做一些像这个问题Spring Security 3 + Random Salt
中提到的问题我有自定义UserDetails和UserDetailsServiceImpl。
现在身份验证时我需要添加自己的逻辑,因为存储在DB中的密码是以django样式完成的,如sha1 $ 1c004 $ f40171c3e790320d88f88f607b5290edeca3225b。
我是否应该重写authenticate方法以拥有自己的逻辑?如果是,那么我必须覆盖哪个类?
以下是我所做的更多细节。
我的spring-security.xml看起来像这样
<authentication-manager>
<authentication-provider user-service-ref="userDetailsServiceImpl">
<password-encoder hash="sha">
<salt-source ref="saltSource" />
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<beans:property name="userPropertyToUse" value="salt" />
</beans:bean>
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="url" value="jdbc:mysql://localhost:3306/db_name" />
<beans:property name="username" value="root" />
<beans:property name="password" value="root" />
</beans:bean>
<beans:bean id="userDetailsServiceImpl" class="com.company.service.impl.UserDetailsServiceImpl">
<beans:property name="dataSource" ref="dataSource" />
</beans:bean>
我的自定义UserDetails类看起来像这样
public class UserDetailsImpl extends User {
/**
*
*/
private static final long serialVersionUID = 1L;
@SuppressWarnings("deprecation")
public UserDetailsImpl(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked,
GrantedAuthority[] authorities, String salt) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired,
accountNonLocked, authorities);
this.salt = salt;
}
private String salt;
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}
我的自定义UserDetailsServiceImpl看起来像这样
public class UserDetailsServiceImpl implements IUserDetailsService {
private DriverManagerDataSource dataSource;
public DriverManagerDataSource getDataSource() {
return dataSource;
}
public void setDataSource(DriverManagerDataSource dataSource) {
this.dataSource = dataSource;
}
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
String sql = "SELECT au.username, au.password, au.is_active, pu.role " +
" FROM auth_user au, profile_userprofile pu WHERE au.id = pu.user_id " +
" AND au.username like :username ";
MapSqlParameterSource source = new MapSqlParameterSource();
source.addValue("username", username);
SimpleJdbcTemplate sjt = new SimpleJdbcTemplate(getDataSource());
User user = sjt.queryForObject(sql, new UserMapper(), source);
String _password = user.getPassword();
return user;
}
private GrantedAuthority[] getAuthorities(String role) {
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
authList.add(new GrantedAuthorityImpl("ROLE_USER"));
if(role.equals("admin"))
authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
return authList.toArray(new GrantedAuthority[] {});
}
private class UserMapper implements ParameterizedRowMapper<User> {
public User mapRow(ResultSet rs, int arg1) throws SQLException {
// getting salt from the stored password
// and setting it in my custom User object
String _password = rs.getString("password");
String password[] = _password.split("\\$");
String salt = password[1];
return new UserDetailsImpl(rs.getString("username"), rs.getString("password"), rs.getInt("is_active") == 1 ? true : false,
true, true, true, getAuthorities(rs.getString("role")), salt);
}
}
}