在JHipster项目中,用户使用邮箱进行注册,注册成功后将发送账户激活链接到邮箱,用户点击链接后,激活成功。
AccountResource类代码:
/**
* {@code POST /register} : register the user.
*
* @param managedUserVM the managed user View Model.
* @throws InvalidPasswordException {@code 400 (Bad Request)} if the password is incorrect.
* @throws EmailAlreadyUsedException {@code 400 (Bad Request)} if the email is already used.
* @throws LoginAlreadyUsedException {@code 400 (Bad Request)} if the login is already used.
*/
@PostMapping("/register")
@ResponseStatus(HttpStatus.CREATED)
public void registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) {
if (isPasswordLengthInvalid(managedUserVM.getPassword())) {
throw new InvalidPasswordException();
}
User user = userService.registerUser(managedUserVM, managedUserVM.getPassword());
mailService.sendActivationEmail(user);
}
UserService类代码:
public User registerUser(AdminUserDTO userDTO, String password) {
userRepository
.findOneByLogin(userDTO.getLogin().toLowerCase())
.ifPresent(
existingUser -> {
boolean removed = removeNonActivatedUser(existingUser);
if (!removed) {
throw new UsernameAlreadyUsedException();
}
}
);
userRepository
.findOneByEmailIgnoreCase(userDTO.getEmail())
.ifPresent(
existingUser -> {
boolean removed = removeNonActivatedUser(existingUser);
if (!removed) {
throw new EmailAlreadyUsedException();
}
}
);
User newUser = new User();
String encryptedPassword = passwordEncoder.encode(password);
newUser.setLogin(userDTO.getLogin().toLowerCase());
// new user gets initially a generated password
newUser.setPassword(encryptedPassword);
newUser.setFirstName(userDTO.getFirstName());
newUser.setLastName(userDTO.getLastName());
if (userDTO.getEmail() != null) {
newUser.setEmail(userDTO.getEmail().toLowerCase());
}
newUser.setImageUrl(userDTO.getImageUrl());
newUser.setLangKey(userDTO.getLangKey());
// new user is not active
newUser.setActivated(false);
// new user gets registration key
newUser.setActivationKey(RandomUtil.generateActivationKey());
Set<Authority> authorities = new HashSet<>();
authorityRepository.findById(AuthoritiesConstants.USER).ifPresent(authorities::add);
newUser.setAuthorities(authorities);
userRepository.save(newUser);
log.debug("Created Information for User: {}", newUser);
return newUser;
}
这里两个关键User字段:activated, activationKey,在User实体类中activated属于必需属性,而activationKey则属于临时属性,JHipster采用@JsonIgnore进行注解,当进行序列化或者反序列化时,Pojo对象将不转换该属性信息。如下:
private boolean activated = false;
@Size(min = 2, max = 10)
@Field("lang_key")
private String langKey;
@Size(max = 256)
@Field("image_url")
private String imageUrl;
@Size(max = 20)
@Field("activation_key")
@JsonIgnore
private String activationKey;
@Size(max = 20)
@Field("reset_key")
@JsonIgnore
private String resetKey;
@Field("reset_date")
private Instant resetDate = null;
用户点击邮件中的链接,例如:
http://127.0.0.1:9000/account/activate?key=5RfmrcsxqxbgoBg2GGjq
后端会根据key值进行校验,代码如下:
public Optional<User> activateRegistration(String key) {
log.debug("Activating user for activation key {}", key);
return userRepository
.findOneByActivationKey(key)
.map(
user -> {
// activate given user for the registration key.
user.setActivated(true);
user.setActivationKey(null);
userRepository.save(user);
log.debug("Activated user: {}", user);
return user;
}
);
}
根据同样原理,当用户需要重置密码时,用户填写注册时使用的邮箱并提交重置密码请求,系统会发送包含密码重置链接邮件:
http://127.0.0.1:9000/account/reset/finish?key=F6WMyIwMSeGzY4E9TxS3
点击链接后,显示填写重置密码的页面,提交后系统根据key进行查询,并且限制链接24小时内有效,代码如下:
public Optional<User> completePasswordReset(String newPassword, String key) {
log.debug("Reset user password for reset key {}", key);
return userRepository
.findOneByResetKey(key)
.filter(user -> user.getResetDate().isAfter(Instant.now().minusSeconds(86400)))
.map(
user -> {
user.setPassword(passwordEncoder.encode(newPassword));
user.setResetKey(null);
user.setResetDate(null);
userRepository.save(user);
return user;
}
);
}
Good Luck,
Cheers!