Woj*_*tek 9 java validation spring spring-data-rest
我正在使用Spring Boot Data REST来保存我的User
实体
@Entity
public class User {
@Id
@GeneratedValue
private long id;
@NotEmpty
private String firstName;
@NotEmpty
private String lastName;
@NotEmpty
private String email;
@Size(min = 5, max = 20)
private String password;
// getters and setters
}
Run Code Online (Sandbox Code Playgroud)
使用存储库:
public interface UserRepository extends CrudRepository<User, Long> {}
Run Code Online (Sandbox Code Playgroud)
我想要做的是首先验证POST
ed用户:
@Configuration
public class CustomRestConfiguration extends SpringBootRepositoryRestMvcConfiguration {
@Autowired
private Validator validator;
@Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", validator);
}
}
Run Code Online (Sandbox Code Playgroud)
并且只有在将用户密码存储到数据库之前才对其进行哈希处理:
@Component
@RepositoryEventHandler(User.class)
public class UserRepositoryEventHandler {
private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
@HandleBeforeCreate
public void handleUserCreate(User user) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
}
}
Run Code Online (Sandbox Code Playgroud)
事实证明,验证是在密码散列后执行的,因此由于散列密码太长而失败.
有没有办法指示Spring首先执行验证,然后才对密码进行哈希处理?我知道我可以自己编写一个控制器,并以细粒度的方式指定所有内容,但我宁愿把它作为我的最后手段.
As I investigated in the debugger it turned out that an incoming entity is processed in the following order:
SpringValidatorAdapter::validate
. The password here is in plain text.@HandleBeforeCreate
is invoked and the password is hashed.BeanValidationEventListener::validate
.Solution 1 (full validation in both phases)
我发现的一种解决方案是password
通过仅使用@NotEmpty
(以便两个验证阶段都通过并且仍然检查传入的 JSON 是否为空/无效)来放松对该字段的约束,并执行原始密码的大小验证@HandleBeforeCreate
(并抛出适当的异常如果需要的话就在那里)。
该解决方案的问题在于它要求我编写自己的异常处理程序。为了跟上 Spring Data REST 在错误响应主体方面设定的高标准,我必须为这一简单的情况编写大量代码。此处描述了执行此操作的方法。
解决方案 2(没有 JPA 实体验证的 Spring bean 验证)
正如Bohuslav Burghardt所暗示的,可以禁用 JPA 完成的第二个验证阶段。这样您就可以保留最小和最大约束,同时避免编写任何额外的代码。一如既往,这是简单性和安全性之间的权衡。这里描述了禁用 JPA 的方法。
解决方案 3(仅保留最小密码长度限制)
另一个解决方案(至少在我的情况下有效)是不限制最大密码长度。这样,在第一个验证阶段,检查密码是否太短,在第二阶段,每次都有效验证(因为加密的密码已经足够长)。
这个解决方案的唯一警告是,它@Size(min = 5)
似乎没有检查无效性,所以我必须添加@NotNull
来处理这种情况。总而言之,该字段注释为:
@NotNull
@Size(min = 5)
private String password;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1942 次 |
最近记录: |