4-Password Encoding and Reset Password

讲到密码加密这一点,我们应该很容易接受,我们存在数据库中的密码不可能是明文方式,以前我们都是使用md5这样的算法来加密密码或者使用sha的方式来加密,现在它们都被新宠BCryptPasswordEncoder夺取了光彩。

我们在使用加密的密码时,其实使用方式很简单,配置也很简单。先看一下我们的使用方式

就是很简单地调用了encode(),由于我们没有之间写登录的实现,所以我们没有一个直接的密码比较的过程。相反我们只需要做好配置就行了。

配置就是注入一个Bean,同时我们看到了在authProvider()我们使用到了encoder(),有了它们spring-security就“自动”完成登录验证。

上面的配置和使用,都是比较简单的,然后让我们回到“重置密码”。

先梳理一下重置密码的流程:

  1. 登录页面,用户点击“重置密码”按钮 ;
  2. 跳转到重置密码页面 ;
  3. 用户输入email地址,再点击“重置”按钮 ;
  4. 后台发送邮件给用户,生成重置密码链接 ;
  5. 用户收到邮件后点击链接,跳转到重置密码,输入新密码,提交 ;
  6. 后台处理,完成密码重置的过程。

对于用户的交互的流程是1、3、5;其余是都是程序处理。对于整个流程而言是有点长,但还是可以接受。我们写代码的思路也就清醒起来。

首先是忘记密码页面forgetPassword.html,一个输入框和一个重置按钮,比较简单。

然后就是重置按钮提交给后台的处理:

我们仍然采用事件机制,发布一个重置密码事件。

重置密码事件的处理也很简单就是发送邮件:

然后用户邮箱应该受到这样一封邮件

当用户点击上面的链接应该跳转到修改密码页面

上面使用到了SecurityContextHolder这个工具类,设置了Authentication,这是因为后面处理保存密码的时候需要使用用户信息。

最后填写好新密码及确认密码后提交给后台处理

用户密码更新完成后再次跳转到登录页面,然后使用新密码就可以登录了。

至此,我们完成了重置密码的所有编码工作。最后让我看下一共修改了哪些文件。

①IUserService中共添加4个接口

②MvcConfig中添加了2行

③OldRegistrationController添加了3个接口

④WebSecurityConfig中添加了3个放行url

⑤java文件中新增了实体类PasswordResetToken和相应的Repo,还有OnResetPasswordEvent和ResetPasswordListener

html文件中新增了forgetPassword.html和updatePassword.html

小结:总体上,完成密码重置的编码工作不是很复杂,只要上面的流程清晰,加上用到了前面java mail,spring事件处理,还有spring security中的一个工具类SecurityContextHolder和UsernamePasswordAuthenticationToken,它们完成了请求上下文中认证信息的传递。

具体的代码可以参见github.

3-Resend Verification Email

上一篇文章中,我们讲到发送邮件激活账号,同时我们还引入了一个过期时间问题,那么如果我们的用户在很久之后才去点击激活链接,显然会受到一个token已经过期的提示,但是同时我们希望可以让用户重新发送一封激活邮件,这是可以让用户重新输入一次邮箱地址,但是更好的做法是只需要用户点一下“重新发送”按钮,然后受到一封有“新”的token的邮件即可。

此时用户看到的token也变化了,如果再用以前的token,就会是一个无效的token了,和原来token关联的那条记录token的有效期延长了。好了我们看看具体怎么做。

1.先看一下我们的一共修改的文件

在OldRegistrationController中我们添加下面的代码

同时我们重构了OnRegistrationCompleteEvent,添加了一个token和构造方法

同时我们还重构了RegistrationListener

在自定义异常处理中我们添加了MailAuthenticationException

最后我们的UserServiceImpl添加了两个实现

还有MvcConfig中添加了一行代码,用于MailError.html

至此我们的改动工作全部完成了。

我们点击上面的Resend按钮后,我们可以收到新的邮件。

在你点击上面的邮件链接后,你会看到

现在正准备登录,可能你忘记了上次输入的密码,那么这时候,我们就要写一个功能“忘记密码”。这个留到下一篇文章。

具体的代码可以参见github.