Spring Security Registration – Resend Verification Email – Spring安全注册 – 重新发送验证邮件

最后修改: 2015年 2月 21日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial – we’re continuing the ongoing Registration with Spring Security series with a look at resending the verification link to the user in case it expires before they have a chance to activate their account.

在本教程中,我们将继续正在进行的用Spring Security进行注册系列,看看如何将验证链接重新发送给用户,以防在他们有机会激活他们的账户之前就过期。

2. Resend the Verification Link

2.重新发送验证链接

First, let’s see we what happens when the user requests another verification link, in case the previous one expired.

首先,让我们看看当用户要求另一个验证链接时,会发生什么情况,以防之前的链接过期。

First – we’ll reset the existing token with a new expireDate. The, we’ll send the user a new email, with the new link/token:

首先,我们将用一个新的expireDate重置现有的令牌。然后,我们将向用户发送一封新的电子邮件,并附上新的链接/令牌。

@GetMapping("/user/resendRegistrationToken")
public GenericResponse resendRegistrationToken(
  HttpServletRequest request, @RequestParam("token") String existingToken) {
    VerificationToken newToken = userService.generateNewVerificationToken(existingToken);
    
    User user = userService.getUser(newToken.getToken());
    String appUrl = 
      "http://" + request.getServerName() + 
      ":" + request.getServerPort() + 
      request.getContextPath();
    SimpleMailMessage email = 
      constructResendVerificationTokenEmail(appUrl, request.getLocale(), newToken, user);
    mailSender.send(email);

    return new GenericResponse(
      messages.getMessage("message.resendToken", null, request.getLocale()));
}

And the utility for actually building the email message the user gets – constructResendVerificationTokenEmail():

还有用于实际构建用户收到的电子邮件的工具 – constructResendVerificationTokenEmail()

private SimpleMailMessage constructResendVerificationTokenEmail
  (String contextPath, Locale locale, VerificationToken newToken, User user) {
    String confirmationUrl = 
      contextPath + "/regitrationConfirm.html?token=" + newToken.getToken();
    String message = messages.getMessage("message.resendToken", null, locale);
    SimpleMailMessage email = new SimpleMailMessage();
    email.setSubject("Resend Registration Token");
    email.setText(message + " rn" + confirmationUrl);
    email.setFrom(env.getProperty("support.email"));
    email.setTo(user.getEmail());
    return email;
}

We also need to modify the existing registration functionality – by adding some new information on the model about the expiration of the token:

我们还需要修改现有的注册功能–通过在模型上添加一些新的信息关于令牌的到期日

@GetMapping("/registrationConfirm")
public String confirmRegistration(
  Locale locale, Model model, @RequestParam("token") String token) {
    VerificationToken verificationToken = userService.getVerificationToken(token);
    if (verificationToken == null) {
        String message = messages.getMessage("auth.message.invalidToken", null, locale);
        model.addAttribute("message", message);
        return "redirect:/badUser.html?lang=" + locale.getLanguage();
    }

    User user = verificationToken.getUser();
    Calendar cal = Calendar.getInstance();
    if ((verificationToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) {
        model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale));
        model.addAttribute("expired", true);
        model.addAttribute("token", token);
        return "redirect:/badUser.html?lang=" + locale.getLanguage();
    }

    user.setEnabled(true);
    userService.saveRegisteredUser(user);
    model.addAttribute("message", messages.getMessage("message.accountVerified", null, locale));
    return "redirect:/login.html?lang=" + locale.getLanguage();
}

3. Exception Handler

3.异常处理程序

The previous functionality is, under certain conditions – throwing exceptions; these exceptions need to be handled, and we’re going to do that with a custom exception handler:

前面的功能在某些条件下–抛出异常;这些异常需要被处理,我们要用自定义异常处理程序来处理。

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @Autowired
    private MessageSource messages;

    @ExceptionHandler({ UserNotFoundException.class })
    public ResponseEntity<Object> handleUserNotFound(RuntimeException ex, WebRequest request) {
        logger.error("404 Status Code", ex);
        GenericResponse bodyOfResponse = new GenericResponse(
          messages.getMessage("message.userNotFound", null, request.getLocale()), "UserNotFound");
        
        return handleExceptionInternal(
          ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
    }

    @ExceptionHandler({ MailAuthenticationException.class })
    public ResponseEntity<Object> handleMail(RuntimeException ex, WebRequest request) {
        logger.error("500 Status Code", ex);
        GenericResponse bodyOfResponse = new GenericResponse(
          messages.getMessage(
            "message.email.config.error", null, request.getLocale()), "MailError");
        
        return handleExceptionInternal(
          ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
    }

    @ExceptionHandler({ Exception.class })
    public ResponseEntity<Object> handleInternal(RuntimeException ex, WebRequest request) {
        logger.error("500 Status Code", ex);
        GenericResponse bodyOfResponse = new GenericResponse(
          messages.getMessage(
            "message.error", null, request.getLocale()), "InternalError");
        
        return handleExceptionInternal(
          ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
    }
}

Note that:

请注意,。

  • we used @ControllerAdvice annotation to handle exceptions across the whole application
  • we used a simple object GenericResponse to send the response:
public class GenericResponse {
    private String message;
    private String error;

    public GenericResponse(String message) {
        super();
        this.message = message;
    }

    public GenericResponse(String message, String error) {
        super();
        this.message = message;
        this.error = error;
    }
}

4. Modify badUser.html

4.修改badUser.html

We’ll now modify badUser.html by enabling the user to get a new VerificationToken only if their token expired:

我们现在要修改badUser.html,使用户只有在他们的令牌过期时才能得到一个新的VerificationToken

<html>
<head>
<title th:text="#{label.badUser.title}">bad user</title>
</head>
<body>
<h1 th:text="${param.message[0]}">error</h1>
<br>
<a th:href="@{/user/registration}" th:text="#{label.form.loginSignUp}">
  signup</a>

<div th:if="${param.expired[0]}">
<h1 th:text="#{label.form.resendRegistrationToken}">resend</h1>
<button onclick="resendToken()" 
  th:text="#{label.form.resendRegistrationToken}">resend</button>
 
<script src="jquery.min.js"></script>
<script type="text/javascript">

var serverContext = [[@{/}]];

function resendToken(){
    $.get(serverContext + "user/resendRegistrationToken?token=" + token, 
      function(data){
            window.location.href = 
              serverContext +"login.html?message=" + data.message;
    })
    .fail(function(data) {
        if(data.responseJSON.error.indexOf("MailError") > -1) {
            window.location.href = serverContext + "emailError.html";
        }
        else {
            window.location.href = 
              serverContext + "login.html?message=" + data.responseJSON.message;
        }
    });
}
</script>
</div>
</body>
</html>

Notice that we’ve used some very basic javascript and JQuery here to handle the response of “/user/resendRegistrationToken” and redirect the user based on it.

注意,我们在这里使用了一些非常基本的javascript和JQuery来处理”/user/resendRegistrationToken “的响应,并根据它重定向用户。

5. Conclusion

5.结论

In this quick article we allowed the user to request a new verification link to activate their account, in case the old one expired.

在这篇快速文章中,我们允许用户请求一个新的验证链接来激活他们的账户,以防旧的验证链接过期。

The full implementation of this tutorial can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

本教程的完整实现可以在github 项目中找到 – 这是一个基于 Eclipse 的项目,因此应该很容易导入并按原样运行。

Next »

Registration with Spring Security – Password Encoding

« Previous

Registration – Activate a New Account by Email