开发者

Spring Security 3: Salting password issue

开发者 https://www.devze.com 2023-02-10 03:08 出处:网络
I have got an simple application made in which I am able to register users and authenticate them. I\'ve got the passwords encoded using and successfully able to authenticate them. I am using Spring 3,

I have got an simple application made in which I am able to register users and authenticate them. I've got the passwords encoded using and successfully able to authenticate them. I am using Spring 3, Spring Security 3 and Hibernate 3 in my application.

Now I want to salt their passwords with the ID of the user but I am not able to achieve this functionality. Could someone help me achieve it? I've been trying to do it for quite some time but ain't able to get it done.

Here is the code I've got for salting users with their ID and authenticating them.

xyz-security.xml

<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/welcome.do" access="hasRole('ROLE_USER')" /> 
    <form-login login-page="/login.do" authentication开发者_开发百科-failure-url="/login.do?login_error=1"/>       
    <logout invalidate-session="true" logout-url="/logout" logout-success-url="/"/>
</http>

<beans:bean id="daoAuthenticationProvider"  class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>

<beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <beans:property name="providers">
        <beans:list>
            <beans:ref local="daoAuthenticationProvider" />
        </beans:list>
    </beans:property>
</beans:bean>

<authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder ref="passwordEncoder">                
            <salt-source ref="saltSource"/>
            </password-encoder>
    </authentication-provider>
</authentication-manager>

<!-- For hashing and salting user passwords -->
<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>
<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource"
    p:userPropertyToUse="id"/>

UserDetailsAdapter.java

@Service("userDetailsAdapter")
public class UserDetailsAdapter {   

    private Long id;

    org.springframework.security.core.userdetails.User buildUserFromUserEntity(User userEntity) {
        String username = userEntity.getUsername();
        String password = userEntity.getPassword();
        boolean enabled = userEntity.isEnabled();
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for (String authority: userEntity.getAuthorities()) {

            authorities.add(new GrantedAuthorityImpl(authority));
        }

        this.id = userEntity.getId();

        org.springframework.security.core.userdetails.User user = new org.springframework.security.core.userdetails.User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
        return user;
    }

    public Long getId() {
        return id;
    }

}

UserDetailsServiceImpl

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserDetailsAdapter userDetailsAdapter;

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        UserDetails userDetails = null;
        User userEntity = userDao.findByUsername(username);

        if (userEntity == null) {
          throw new UsernameNotFoundException("user not found");
        }
        userDetails = userDetailsAdapter.buildUserFromUserEntity(userEntity);

        return userDetails;
    }
}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private SaltSource saltSource;

    public User getByUsername(String username) {
        return userDao.findByUsername(username);
    }

    public User getByEmail(String email) {
        return userDao.findByEmail(email);
    }

    public void createUser(User user) {
        userDao.create(user);

        UserDetailsAdapter userDetailsAdapter = new UserDetailsAdapter();
        org.springframework.security.core.userdetails.User userDetails =  userDetailsAdapter.buildUserFromUserEntity(user);
        String password = userDetails.getPassword();
        Object salt = saltSource.getSalt(userDetails);
        user.setPassword(passwordEncoder.encodePassword(password, salt));
        userDao.update(user);

    }

    public void updateUser(User user) {
        userDao.update(user);
    }
}

Could someone help me understand what am I missing here? Many thanks.


ReflectionSaltSource extracts a salt from the instance of UserDetails. But you use org.springframework.security.core.userdetails.User as an implementation of UserDetails, and it doesn't have a property named id (instead of that you have this property in UserDetailsAdapter, that doesn't make sense, since UserDetailsAdapter is a singleton).

So, you need to create a subclass of org.springframework.security.core.userdetails.User with id property, and return it from your UserDetailsAdapter.


Here are the updated files that made it working:

UserDetailsAdapter.java

public class UserDetailsAdapter extends org.springframework.security.core.userdetails.User {
    private final Long id;
    public UserDetailsAdapter(User userEntity) {

        super(userEntity.getUsername(), userEntity.getPassword(), userEntity.isEnabled(), true, true, true, toAuthorities(userEntity.getAuthorities()));
        this.id = userEntity.getId();
    }

    private static Collection<GrantedAuthority> toAuthorities(List<String> authorities) {
        Collection<GrantedAuthority> authorityList = new ArrayList<GrantedAuthority>();
        for (String authority: authorities) {
            authorityList.add(new GrantedAuthorityImpl(authority));
        }
        return authorityList;
    }

    public Long getId() {
        return id;
    }

}

UserDetailsServiceImpl.java

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        UserDetails userDetails = null;
        User userEntity = userDao.findByUsername(username);

        if (userEntity == null) {
          throw new UsernameNotFoundException("user not found");
        }
        userDetails = new UserDetailsAdapter(userEntity);

        return userDetails;
    }
}

UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {
...
    public void createUser(User user) {
        userDao.create(user);

        UserDetailsAdapter userDetails = new UserDetailsAdapter(user);
        String password = userDetails.getPassword();
        Object salt = saltSource.getSalt(userDetails);
        user.setPassword(passwordEncoder.encodePassword(password, salt));
        userDao.update(user);

    }
...
}

Thanks :)

0

精彩评论

暂无评论...
验证码 换一张
取 消