1. 用户注册
1.1 发送验证码
- 使用 Redis 缓存存储指定生存时间验证码,其中手机号为 key,值的时间戳 + 验证码。时间戳的作用用于实现用户执行时间内不能重复发送验证码;
- 验证码的发送采阿里云第三方服务实现,传入指定手机号和验证码;
- 缓存中的验证码未过期且与用户的验证码相互匹配,且此时支持再次发送验证码,那么再次调用第三方服务发送验证码;
- 缓存中的验证码已经过期,那么生成新的验证码并调用第三方服务发送验证码。
1.2 用户密码加密
为了保证用户的数据安全,用户的密码需要以密文的方式存储到数据库中,如下是几种加密策略:
1.2.1 MD5 加密
可以使用 MD5 工具类实现密码进行加密,虽然 MD5 加密是不可逆的,但是可能会被暴力破解
1.2.2 MD5 盐值加密
在 MD5 加密的基础上,可以生成一段随机的盐值(随机序列)并按照自定义拼接规则(避免通过盐值反向破解)与对密码进行拼接,不过这个盐值需要存储到数据库中。此方法虽然可以避免密码被破解,但是需要向数据库存储盐值。
1.2.3 BCrypt 加密
spring security 提供了一个加密工具,可以实现比 MD5 盐值加密更便捷和优异的加密结果,代码示例如下:
1 | //1. 密码加密逻辑 |
2. 分布式 Session 共享和 SpringSession 原理
2.1 Session 共享问题
在单服务应用下,用户使用浏览器登录成功后,后台会生成一个指定 sessioId 的 Cookie 并命令浏览器保存起来。用户下次进行访问网站时就可以带上该 Cookie 进行用户验证通过时就可以免登录操作。
但是单服务应用下,不能跨子域名和多服务共享 session。如下图,比如存在多个会员服务,因为存在第一个会员服务存在 session 而第二个会员服务不存在 session,那么就存在服务之间的共享问题。而对于不同的服务则存在跨域名 session 共享问题,比如用户使用会员服务登录成功后获取到 session,但是订单服务则无法获取。
2.2 Session 共享问题解决策略
1)Session 复制同步方案:比如不同 tomcat 之间进行 session 复制同步共享
2)客户端以 Cookie 形式存储 session
3)Hash 一致性:将不同的 IP 以 hash 形式映射到多台服务器上,由指定服务器存储对应 session 信息
4)统一 session 存储
5)跨域名-子域 session 共享问题
前面已经说过,普通的 session 机制对于不同子域名之间的 session 共享是不起作用的,即不同域名之间无法进行 session 共享。但是我们可以设置 session 的作用域,即扩大其作用域到父域名上,这样不同的子域就可以实现 session 共享。
2.3 SpringSession 原理
SpringSession 是 Spring 提供的一个分布式 session 共享框架,其可以采用公共的存储容器(MongoDB、Redis)来存储多个服务的 Session 信息,并支持设置 Session 的作用域,其可以简单的解决 Session 共享问题。
如下是 SpringSession 的核心代码,其重点就是 SpringSession 对原有的 Session 对应进行了重新和包装(装饰者模式),后面我们在登录成功后往前端生成返回 Cookie 时的 Sesssion 对象就是 SpringSession 包装后的。
3. 用户登录
3.1 OAuth2 社交账号登录
社交登录流程如下所示:
3.2 单点登录
下图是存在认证中心的分布式单点登录流程: