How to use new PasswordEncoder from Spring Security

前端 未结 4 947
走了就别回头了
走了就别回头了 2020-12-01 01:16

As of Spring Security 3.1.4.RELEASE, the old org.springframework.security.authentication.encoding.PasswordEncoder has been deprecated in favour of org.spr

相关标签:
4条回答
  • 2020-12-01 01:43

    I had a similar issue. I needed to keep the legacy encrypted passwords (Base64/SHA-1/Random salt Encoded) as users will not want to change their passwords or re-register. However I wanted to use the BCrypt encoder moving forward too.

    My solution was to write a bespoke decoder that checks to see which encryption method was used first before matching (BCrypted ones start with $).

    To get around the salt issue, I pass into the decoder a concatenated String of salt + encrypted password via my modified user object.

    Decoder

    @Component
    public class LegacyEncoder implements PasswordEncoder {
    
        private static final String BCRYP_TYPE = "$";
        private static final PasswordEncoder BCRYPT = new BCryptPasswordEncoder();
    
        @Override
        public String encode(CharSequence rawPassword) {
    
        return BCRYPT.encode(rawPassword);
        }
    
        @Override
        public boolean matches(CharSequence rawPassword, String encodedPassword) {
    
        if (encodedPassword.startsWith(BCRYP_TYPE)) {
            return BCRYPT.matches(rawPassword, encodedPassword);
        }
    
        return sha1SaltMatch(rawPassword, encodedPassword);
        }
    
        @SneakyThrows
        private boolean sha1SaltMatch(CharSequence rawPassword, String encodedPassword) {
    
        String[] saltHash = encodedPassword.split(User.SPLIT_CHAR);
    
        // Legacy code from old system   
        byte[] b64salt = Base64.getDecoder().decode(saltHash[0].getBytes());
        byte[] validHash = Base64.getDecoder().decode(saltHash[1]);
        byte[] checkHash = Utility.getHash(5, rawPassword.toString(), b64salt);
    
        return Arrays.equals(checkHash, validHash);
        }
    
    }
    

    User Object

    public class User implements UserDetails {
    
        public static final String SPLIT_CHAR = ":";
    
        @Id
        @Column(name = "user_id", nullable = false)
        private Integer userId;
    
        @Column(nullable = false, length = 60)
        private String password;
    
        @Column(nullable = true, length = 32)
        private String salt;
    

    .
    .

        @PostLoad
        private void init() {
    
        username = emailAddress; //To comply with UserDetails
        password = salt == null ? password : salt + SPLIT_CHAR + password;
        }        
    

    You can also add a hook to re-encode the password in the new BCrypt format and replace it. Thus phasing out the old method.

    0 讨论(0)
  • 2020-12-01 01:54

    If you haven't actually registered any users with your existing format then you would be best to switch to using the BCrypt password encoder instead.

    It's a lot less hassle, as you don't have to worry about salt at all - the details are completely encapsulated within the encoder. Using BCrypt is stronger than using a plain hash algorithm and it's also a standard which is compatible with applications using other languages.

    There's really no reason to choose any of the other options for a new application.

    0 讨论(0)
  • 2020-12-01 01:54

    Having just gone round the internet to read up on this and the options in Spring I'd second Luke's answer, use BCrypt (it's mentioned in the source code at Spring).

    The best resource I found to explain why to hash/salt and why use BCrypt is a good choice is here: Salted Password Hashing - Doing it Right.

    0 讨论(0)
  • 2020-12-01 01:55

    Here is the implementation of BCrypt which is working for me.

    in spring-security.xml

    <authentication-manager >
        <authentication-provider ref="authProvider"></authentication-provider>  
        </authentication-manager>
    <beans:bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
      <beans:property name="userDetailsService" ref="userDetailsServiceImpl" />
      <beans:property name="passwordEncoder" ref="encoder" />
    </beans:bean>
    <!-- For hashing and salting user passwords -->
        <beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
    

    In java class

    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    String hashedPassword = passwordEncoder.encode(yourpassword);
    

    For more detailed example of spring security Click Here

    Hope this will help.

    Thanks

    0 讨论(0)
提交回复
热议问题