Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Password encoding with Spring Data REST

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 encode the request's password field, when the client send it via POST, PUT and PATCH.

@Entity
public class User {
  @NotNull
  private String username;
  @NotNull
  private String passwordHash;
  ...
  getters/setters/etc
  ...
}

First I tried to solve with @HandleBeforeCreate and @HandleBeforeSave event listeners but the User in it's argument is already merged, so I can't make any difference between the User's new password, or the old passwordHash:

@HandleBeforeSave
protected void onBeforeSave(User user) {
    if (user.getPassword() != null) {
        account.setPassword(passwordEncoder.encode(account.getPassword()));
    }
    super.onBeforeSave(account);
}

Is that possible, to use @Projection and SpEL on a setter method?

like image 512
Plutoz Avatar asked May 15 '15 13:05

Plutoz


2 Answers

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;
like image 117
robgmills Avatar answered Oct 14 '22 00:10

robgmills


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

like image 2
charybr Avatar answered Oct 13 '22 23:10

charybr