2

この質問で尋ねられているようなことをしなければなりませんSpring Security 3 + Random Salt

カスタムの UserDetails と UserDetailsS​​erviceImpl があります。

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;
}

}

そして、私のカスタム UserDetailsS​​erviceImpl は次のようになります

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);
    }

}

}
4

0 に答える 0