この質問で尋ねられているようなことをしなければなりませんSpring Security 3 + Random Salt
カスタムの UserDetails と UserDetailsServiceImpl があります。
DBに保存されたパスワードはsha1$1c004$f40171c3e790320d88f88f607b5290edeca3225bのようなdjangoスタイルで行われるため、認証中に独自のロジックを追加する必要があります。
認証メソッドをオーバーライドして、独自のロジックを持つ必要がありますか? もしそうなら、私がオーバーライドしなければならないクラスはどれですか?
以下は、私が行ったことの詳細です。
私の 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);
}
}
}