Spring Security 3 + Random Salt + Hash + Custom UserDetails + Custom UserDetailsS​​ervice

时间:2013-01-19 13:01:57

标签: spring security

我必须做一些像这个问题Spring Security 3 + Random Salt

中提到的问题

我有自定义UserDetails和UserDetailsS​​erviceImpl。

现在身份验证时我需要添加自己的逻辑,因为存储在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;
}

}

我的自定义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);
    }

}

}

0 个答案:

没有答案