我有两颗豆子:
CheckPassword
和CheckEmail
@Service("CheckPassword")
@Primary
public class CheckPassword implements CheckStringInterface {
private static final String regex_password = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@#$%^&+=!])(?=\\S+$).{8,20}$";
@Override
public boolean isStringValid(String rawPassword) {
Pattern pattern = Pattern.compile(regex_password);
Matcher matcher = pattern.matcher(rawPassword);
return matcher.matches();
}
}
@Service("CheckEmail")
public class CheckEmail implements CheckStringInterface {
private static final String regex_password = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,6}$";
@Override
public boolean isStringValid(String rawPassword) {
Pattern pattern = Pattern.compile(regex_password);
Matcher matcher = pattern.matcher(rawPassword);
return matcher.matches();
}
}
我使用
@Qualifier
来选择我需要的bean,但为什么只有密码返回true
,而电子邮件总是返回false
?
@Qualifier("CheckPassword")
private final CheckStringInterface checkPasswordFormat;
@Qualifier("CheckEmail")
private final CheckStringInterface checkEmailFormat;
@Qualifier("EmailVerifyCode")
private final VerificationCodeManager verificationCodeManager;
@Value("${email_root}")
private String email_root;
private final SendMailTemplateService sendMailTemplateService;
private static final String template_verify_code_register = "templateVerifyCodeRegister";
private static String message_notification = "Use the code to verify this email: ";
@Transactional
public Integer register(RegisterDTO registerDTO, HttpServletRequest request){
if (userService.findByEmail(registerDTO.email()) == null) {
if (checkPasswordFormat.isStringValid(registerDTO.password()) == false
|| checkEmailFormat.isStringValid(registerDTO.email()) == false) {
log.info("Wrong Format {}", checkPasswordFormat.isStringValid(registerDTO.password()));
log.info("Wrong Format {}", checkEmailFormat.isStringValid(registerDTO.email()));
return 0; // Wrong format email or password
}
User user = new User();
user.setEmail(registerDTO.email());
user.setFullName(registerDTO.fullName());
user.setPassword(registerDTO.password());
user.setCreatedAt(Time.getTheTimeRightNow());
user.setUserVerifyCode(verificationCodeManager.generateCode());
user.setUserVerifyCodeExpirationTime(verificationCodeManager.codeExpiration());
log.info("------> RegisterService | register: register with email {}", user.getEmail());
createUser.create(user);
sendMail(user, user.getUserVerifyCode());
request.getSession().setAttribute("email", registerDTO.email());
return 1; // Create successful
} else {
return 2; // Email already exists
}
}
这是我在 Swagger 上测试 API 时使用的数据:
{
"email": "[email protected]",
"fullName": "abcdABCD",
"password": "Password@1234"
}
我尝试更改为另一个正则表达式,但没有帮助。 当我登录时,我看到密码总是返回
true
,因为我输入了正确的格式,但电子邮件将返回 false
,格式正确和错误。
这并不是一个真正与 springboot 或 spring security 相关的问题,而是一个与正则表达式相关的问题。
我在正则表达式电子邮件验证中发现两个主要问题:
\\\\
字符之前使用了.
,这将使正则表达式期望一个\
(因为要在java中编写反斜杠,您需要\\
,所以另外两个\\
实际上将转义它)并会导致被解释为特殊字符的点,表示“任何字符”根据您当前的设置,
isStringValid("BONBON147852369@GMAIL\\.COM")
返回true
isStringValid("BONBON147852369@GMAIL\\ACOM")
返回true
isStringValid("bONBON147852369@GMAIL\\.COM")
返回false
要修复代码,您只需在点前使用两个反斜杠(而不是 4 个),这样您就可以转义点字符,并且还需要使正则表达式也期望小写字母:
@Service("CheckEmail")
public class CheckEmail implements CheckStringInterface {
private static final String regex_email = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$";
@Override
public boolean isStringValid(String rawEmail) {
// alternative to Pattern.CASE_INSENSITIVE is to include a-z interval in your regex
Pattern pattern = Pattern.compile(regex_email, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(rawEmail);
return matcher.matches();
}
}