整体实现逻辑
1.前端在登录页面时,自动从后台获取最新的验证码图片
2.服务器接收获取生成验证码请求,生成验证码和对应的图片,图片响应回前端,验证码保存一份到服务器的 session 中
3.前端用户登录时携带当前验证码
4.服务器校验验证码是否合法(验证码存在并未过期),继续后续的用户名和密码校验逻辑
通过一个时序图来表述如下图,图中细化了一下各个控制器和过滤器之间的功能职责,还不是很正规,只为了更好表达上述的流程描述,所以读者们将就一下:
![](https://i-blog.csdnimg.cn/blog_migrate/4514d806f6804d64afaa7f5c0377baff.png)
时序图 plantUML 代码
plantUML 的使用教程请移步至之前发布过的文章:PlantUML 语法之时序图
@startuml
hide footbox
skinparam sequenceMessageAlign center
skinparam sequenceArrowFontSize 11
skinparam noteFontSize 11
skinparam monochrome true
skinparam lifelinestrategy solid
autonumber "<b>[000]"
participant browser as ui
participant imageCodeController as ic
participant UserController as uc
database sessionStorage as session
participant CodeAuthenticationFilter as cf
participant "UsernamePasswordAuthenticationFilter" as uf
ui -> ic: 登录请求
ic -> ic: 生成验证码
ic -> session: 保存验证码信息
ic --> ui: 验证码图片
...
autonumber "<b>[000]"
ui -> cf: 帐号登录
cf -> session: 获取验证码
session --> cf: 验证码
cf -> cf: 校验请求验证码合法性
cf -> uf: 用户认证的后续操作
uf --> uc: 返回认证结果
uc --> ui: 用户登录成功
@enduml
将上述的逻辑进行任务拆分:随机验证码和图片生成,生成验证码请求Controller
,session存储器就临时使用spring-social-web
包中的SessionStrategy
来存储,验证码过滤器,配置过滤器到spring scuerity
过滤器中的用户密码验证过滤器之前。
前端控制器+生成验证码
服务器 session 容器
采用小步快走的开发模式,前端控制器和生成验证码的代码都写在一起,后期再进行代码重构, 这里主要引用了spring-social-web
依赖:
<dependency><groupId>org.springframework.social</groupId><artifactId>spring-social-web</artifactId><version>1.1.4.RELEASE</version>
</dependency>
这个包里面有个很小巧的session
管理工具:SessionStrategy
考虑到这个 session 在验证码过滤器中还得使用,所以自定义了一个配置,直接注入到了spring中:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
@Configuration
public