Password encoding with Spring Data REST

前端 未结 3 1373
天涯浪人
天涯浪人 2021-01-13 03:13

How should I encode automatically the subbmitted plain password field of my entity with Spring Data REST?

I\'m using BCrypt encoder and I want to automatically encod

相关标签:
3条回答
  • 2021-01-13 03:53

    You can implement a Jackson JsonDeserializer:

    public class BCryptPasswordDeserializer extends JsonDeserializer<String> {
    
        public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            ObjectCodec oc = jsonParser.getCodec();
            JsonNode node = oc.readTree(jsonParser);
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            String encodedPassword = encoder.encode(node.asText());
            return encodedPassword;
        }
    }
    

    And apply it to your JPA Entity property:

    // The value of the password will always have a length of 
    // 60 thanks to BCrypt
    @Size(min = 60, max = 60)
    @Column(name="password", nullable = false, length = 60)
    @JsonDeserialize(using = BCryptPasswordDeserializer.class )
    private String password;
    
    0 讨论(0)
  • 2021-01-13 03:55

    Some enhancement to @robgmills JsonDeserializer solution:

    • In Spring 5 introduce DelegatingPasswordEncoder. It is more flexible, see spring docs.
    • It is not nesessary to create PasswordEncoder every time at deserialization.
    • A big projects may has several JsonDeserializer's - better make them inner classes.
    • Usually encoding password hidden for get request. I've used @JsonProperty(access = JsonProperty.Access.WRITE_ONLY), see https://stackoverflow.com/a/12505165/548473

    For Spring Boot code looks like:

    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        public static final PasswordEncoder PASSWORD_ENCODER = PasswordEncoderFactories.createDelegatingPasswordEncoder();
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
           auth.userDetailsService(userDetailsService()).passwordEncoder(PASSWORD_ENCODER);
        }
        ....
    
    public class JsonDeserializers {
        public static class PasswordDeserializer extends JsonDeserializer<String> {
            public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                ObjectCodec oc = jsonParser.getCodec();
                JsonNode node = oc.readTree(jsonParser);
                String rawPassword = node.asText();
                return WebSecurityConfig.PASSWORD_ENCODER.encode(rawPassword);
            }
        }
        ...
    
    @Entity
    public class User ...
    
        @Column(name = "password")
        @Size(max = 256)
        @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
        @JsonDeserialize(using = JsonDeserializers.PasswordDeserializer.class)
        private String password;
        ...
    
    0 讨论(0)
  • 2021-01-13 04:02

    Modifying setter method of password field is sufficient, as shown below:

    public void setPassword(String password) {
            PasswordEncoder encoder = new BCryptPasswordEncoder();
            this.password = encoder.encode(password);
        }
    

    Refer: https://github.com/charybr/spring-data-rest-acl/blob/master/bookstore/src/main/java/sample/sdr/auth/bean/UserEntity.java

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