数据库blog_user表结构 :

1.1 发送验证码#
在Service层中首先使用FommatChecker
类校验phone合法性
调用SendSms
类的String sendMessage(String phoneNumbers)
方法:为了避免发布时造成的密码泄露,将key写在application.yml
中,使用@Value
注解进行加载。
1.2 用户登录#
1.
手机号-验证码登录:与Redis中存储的验证码进行 比较,一致则可以登录
2.
手机号-密码登录:令UserService
实现UserDetailsService
接口,利用SpringSecurity
中AuthenticationManager
类的.authenicate
方法。
当验证码不为null时,使用验证码登录;否则使用密码登录。
生成用户的Jwt Token(PayLoad为User Id),存入Redis
1.2.1 手机号-密码登录#
利用了SpringSecuirty
的相关接口方法(或者也可以自己实现一个加密器和ContextHolder
1.
UserService
实现接口UserDetailsService
,重写loadUserByUsername
方法,返回该查找键(此处为phone)对应的UserDetail
类对象:
2.
设置AuthenticationManager
类对象,需要的参数包括对密码进行加密编码的PasswordEncoder
和步骤1中的UserDetailsService
。
3.
调用AuthenticationManager对象的.authenication
方法完成对密码的验证。

1.2.2 JWT的生成与验证#
JWTString=Base64(Header).Base64(Payload).HMACSHA256[Base64(Header).Base64(Payload),secret]
header和payload可以直接利用base64解码出原文,从header中获取哈希签名的算法,从payload中获取有效数据。
signature由于使用了不可逆的加密算法,无法解码出原文,它的作用是校验token有没有被篡改。服务端获取header中的加密算法之后,利用该算法加上secretKey对header、payload进行加密,比对加密后的数据和客户端发送过来的是否一致。
注意secretKey只能保存在服务端,而且对于不同的加密算法其含义有所不同,一般对于MD5类型的摘要加密算法,secretKey实际上代表的是盐值。
注意:由于PayLoad仍然是可解密的,所以不建议在PayLoad中存放敏感信 息。JWT工具类的实现在JwtUtil.java
类中。JwtFilter的实现JwtAuthenticationTokenFilter
继承了OncePerRequestFilter
:request.getHeader("token")
若用户请求不携带token,直接放行
若携带token,调用JwtUtil类解析userId
若解析成功,存入SecurityContextHolder中 1.3 用户注册#
Controller层验证手机号、验证码、密码的格式合法性
1.4 修改用户信息#
校验SecurityContextHolder中的用户id,是否与请求Body中的用户id相同