1概要

このチュートリアルでは、アカウントをアクティブにする機会がある前に期限切れになった場合に、検証リンクをユーザーに再送信することを検討しながら、現在進行中の


Spring Security

シリーズへの登録

を継続しています。


2確認リンクを再送信

まず、前のリンクが期限切れになった場合に備えて、ユーザーが別の確認リンクを要求するとどうなるかを見てみましょう。

まず、既存のトークンを新しい

expireDate

でリセットします。次に、新しいリンク/トークンを付けて、新しい電子メールをユーザーに送信します。

@RequestMapping(value = "/user/resendRegistrationToken", method = RequestMethod.GET)
@ResponseBody
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()));
}

ユーザーが実際に受け取る電子メールメッセージを作成するためのユーティリティ –

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;
}

また、トークンの有効期限に関するモデルに関する新しい情報を追加することによって、既存の登録機能を変更する必要があります。

@RequestMapping(value = "/regitrationConfirm", method = RequestMethod.GET)
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例外ハンドラ

以前の機能は、特定の条件下では例外をスローします。これらの例外は処理される必要があります、そして我々は

カスタム例外ハンドラ

でそれをするつもりです:

@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);
    }
}

ご了承ください:

  • 私たちは、@ @ ControllerAdvice__アノテーションを使って、全体の例外を処理しました

アプリケーション全体
** レスポンスを送るためにシンプルなオブジェクト

GenericResponse

を使いました:

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

badUser.html


を変更します

トークンの有効期限が切れた場合にのみ、ユーザーが新しい

VerificationToken

を取得できるようにして、

badUser.html

を変更します。

<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>

ここでは、「/user/resendRegistrationToken」の応答を処理し、それに基づいてユーザーをリダイレクトするために、非常に基本的なJavaScriptとJQueryを使用しました。


5結論

このクイック記事では、古いアカウントが期限切れになった場合に備えて、ユーザーが自分のアカウントをアクティブにするための新しい確認リンクを要求することを許可しました。

このチュートリアルの

完全な実装

はhttps://github.com/eugenp/spring-security-registration[the github project]にあります – これはEclipseベースのプロジェクトなので、インポートして実行するのは簡単です。そうです。




  • «** 前へ