尝试为与 Spring Boot 匹配的密码模式添加正则表达式
Trying to add a regex for password pattern matching with Spring Boot
我想为注册密码的用户添加模式匹配。在我的用户模型中,我有:
@Column
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$")
private String password;
但是,当我去注册用户时,我收到了 400 Bad Request。
javax.validation.ConstraintViolationException: Validation failed for classes [com.practice.models.AppUser] during persist time for groups [javax.validation.groups.Default, ]\nList of constraint violations:[\n\tConstraintViolationImpl{interpolatedMessage='must match \"^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$\"', propertyPath=password, rootBeanClass=class com.practice.models.AppUser, messageTemplate='{javax.validation.constraints.Pattern.message}'}\n]\n\tat
可以用@Pattern
注解来完成吗?它应该继续出现在模型上吗?
我的控制器端点如下所示:
@PostMapping("/register")
public AppUser register(@Valid @RequestBody AppUser user) {
return appUserService.createUser(user);
}
这是我发送给注册的数据:
{
"username": "Johnny",
"email": "johnny@rosevideo.com",
"password": "P@ssword123",
"passwordConfirmation": "P@ssword123"
}
然后在我的服务层,我用 BCrypt 加密我的密码:
public AppUser createUser(AppUser appUser) {
Optional<AppUser> existingUser = appUserRepo.findByUsername(appUser.getUsername());
if (existingUser.isPresent()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "A user with that username already exists");
}
if (!appUser.getPassword().equals(appUser.getPasswordConfirmation())) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Passwords don't match");
}
String encodedPassword = bCryptPasswordEncoder.encode(appUser.getPassword());
appUser.setPassword(encodedPassword);
return appUserRepo.save(appUser);
}
```
正则表达式有点偏差,您应该使用 \d
而不是 \\d
:
^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$
使用以下正则表达式满足以下条件:
条件:
- 最少 1 个大写字母。
- 最少 1 个小写字母。
- 最少 1 个特殊字符。
- 最少 1 个数。
- 最少 8 个字符。
正则表达式:
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$@!%&*?])[A-Za-z\d#$@!%&*?]{8,}$
正在测试您的正则表达式,它似乎不起作用。我能够快速找到以下密码的正则表达式示例。
^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[^\w\d\s:])([^\s]){8,16}$
此正则表达式仅在满足以下所有条件时才匹配:
- 密码必须包含 1 个数字 (0-9)
- 密码必须包含1个大写字母
- 密码必须包含1个小写字母
- 密码必须包含 1 个非字母数字
- 密码为8-16个字符,无space
https://regex101.com/library/0bH043
这是另一个从字符串构建正则表达式的好网站:
https://regex-generator.olafneumann.org/
当您在密码验证的同时使用密码加密时,通常会发生这种情况。基本上,您的应用目前正在 运行 对加密密码进行模式验证。
在没有额外配置的情况下,@Pattern
注释导致验证 运行 不仅在控制器中使用 @Valid
的地方,而且在调用 appUserRepo.save(appUser)
。这意味着模式匹配是 运行 与散列密码,这很可能与您的模式不匹配。
如果您不想 运行 持久化验证,请将此行添加到您的 application.properties
文件中:
spring.jpa.properties.javax.persistence.validation.mode=none
我想为注册密码的用户添加模式匹配。在我的用户模型中,我有:
@Column
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$")
private String password;
但是,当我去注册用户时,我收到了 400 Bad Request。
javax.validation.ConstraintViolationException: Validation failed for classes [com.practice.models.AppUser] during persist time for groups [javax.validation.groups.Default, ]\nList of constraint violations:[\n\tConstraintViolationImpl{interpolatedMessage='must match \"^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$\"', propertyPath=password, rootBeanClass=class com.practice.models.AppUser, messageTemplate='{javax.validation.constraints.Pattern.message}'}\n]\n\tat
可以用@Pattern
注解来完成吗?它应该继续出现在模型上吗?
我的控制器端点如下所示:
@PostMapping("/register")
public AppUser register(@Valid @RequestBody AppUser user) {
return appUserService.createUser(user);
}
这是我发送给注册的数据:
{
"username": "Johnny",
"email": "johnny@rosevideo.com",
"password": "P@ssword123",
"passwordConfirmation": "P@ssword123"
}
然后在我的服务层,我用 BCrypt 加密我的密码:
public AppUser createUser(AppUser appUser) {
Optional<AppUser> existingUser = appUserRepo.findByUsername(appUser.getUsername());
if (existingUser.isPresent()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "A user with that username already exists");
}
if (!appUser.getPassword().equals(appUser.getPasswordConfirmation())) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Passwords don't match");
}
String encodedPassword = bCryptPasswordEncoder.encode(appUser.getPassword());
appUser.setPassword(encodedPassword);
return appUserRepo.save(appUser);
}
```
正则表达式有点偏差,您应该使用 \d
而不是 \\d
:
^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$
使用以下正则表达式满足以下条件:
条件:
- 最少 1 个大写字母。
- 最少 1 个小写字母。
- 最少 1 个特殊字符。
- 最少 1 个数。
- 最少 8 个字符。
正则表达式:
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$@!%&*?])[A-Za-z\d#$@!%&*?]{8,}$
正在测试您的正则表达式,它似乎不起作用。我能够快速找到以下密码的正则表达式示例。
^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[^\w\d\s:])([^\s]){8,16}$
此正则表达式仅在满足以下所有条件时才匹配:
- 密码必须包含 1 个数字 (0-9)
- 密码必须包含1个大写字母
- 密码必须包含1个小写字母
- 密码必须包含 1 个非字母数字
- 密码为8-16个字符,无space
https://regex101.com/library/0bH043
这是另一个从字符串构建正则表达式的好网站: https://regex-generator.olafneumann.org/
当您在密码验证的同时使用密码加密时,通常会发生这种情况。基本上,您的应用目前正在 运行 对加密密码进行模式验证。
在没有额外配置的情况下,@Pattern
注释导致验证 运行 不仅在控制器中使用 @Valid
的地方,而且在调用 appUserRepo.save(appUser)
。这意味着模式匹配是 运行 与散列密码,这很可能与您的模式不匹配。
如果您不想 运行 持久化验证,请将此行添加到您的 application.properties
文件中:
spring.jpa.properties.javax.persistence.validation.mode=none