博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[译] 学习 Spring Security(五):重发验证邮件
阅读量:6002 次
发布时间:2019-06-20

本文共 5197 字,大约阅读时间需要 17 分钟。

作者:Eugen Paraschiv

译者:oopsguy.com

1、概述

在本教程中,我们将继续 Spring Security 系列中的注册流程,在用户激活帐户之前重发验证链接给用户。

2、重发验证链接

首先,当用户请求另一个验证链接时,我们需要防上一个验证链接发生过期。

我们将用新的 expireDate 重置现有的令牌,之后向用户发送一封新邮件,并附上新的链接和令牌:

@RequestMapping(value = "/user/resendRegistrationToken", method = RequestMethod.GET)@ResponseBodypublic 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、异常处理

以前的功能是在某些情况下抛出异常,这些异常需要处理,我们将使用自定义的异常处理程序来处理这些异常:

@ControllerAdvicepublic class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {     @Autowired    private MessageSource messages;     @ExceptionHandler({ UserNotFoundException.class })    public ResponseEntity 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 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 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

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

bad user

error

signup

resend

复制代码

请注意,我们在这里使用了一些非常简单的 JavaScript 和 JQuery 来处理 /user/resendRegistrationToken 的响应,并根据它重定向用户。

5、结论

在本文中,我们允许用户重新请求一个新的验证链接来激活账户,以防旧账户过期。

本教程的完整实现可以在 项目中找到 — 这是一个基于 Eclipse 的项目,应该很容易导入和运行。

原文项目地址

转载地址:http://mozmx.baihongyu.com/

你可能感兴趣的文章
Spark SQL 报错总结
查看>>
DOS命令安装系统服务
查看>>
Oracle技术之SYS用户对象不支持延迟段
查看>>
Linux下升级 OpenSSH
查看>>
git操作详解
查看>>
JAVA枚举(一)引入枚举知识点的前戏
查看>>
java多线程编程之简介
查看>>
关于已经上线项目的升级的启示
查看>>
jquery 纯js右下角弹窗
查看>>
标准功能模块组件 -- 名片管理组件,C\S 版本的标准用例程序,可以参考权限实现方法...
查看>>
看看一个朋友写的代码,大家发表发表意见,比较简单的代码
查看>>
CentOS 6.0下vncserver安装配置
查看>>
ZooKeeper-3.4.6学习笔记汇总
查看>>
Apache Shiro学习笔记(二)身份验证subject.login过程
查看>>
我的友情链接
查看>>
Linux查看CPU和内存使用情况
查看>>
bootstrap-程序输出
查看>>
Spring4-自动装配Beans-缺省情况下,自动配置是通过“ref”属性手动设定
查看>>
Linux上挂载新硬盘详解
查看>>
环网相关问题
查看>>