8-25 session存储、登录认证、权限认证解决方案初步学习
本章节将围绕登录功能的实现,来搭建
- sessin存储方案
- 登录认证方案
- 权限验证方案
一、整体思路分析
1.1 登录思路
登录的目的:
- 验证登录信息是否正确
- 生成token令牌:在登录之后,当访问那些需要登录才能访问的接口时,放置令牌在请求中是证明我们登录过的手段
- 存储session到数据库:session是什么,为什么要存储session,后面会介绍到
整体思路分析
- 效验数据:验证账号密码是否正确
- 写session:提供我们在项目的任何地方
- 生成并设置token:创建令牌
- 存储session到数据库
- 获取role:获取当前用户的role
- 封装sessionWrapper
1.2 session存储方案
- 将session信息在登录的时候整理,存储在数据库中
- 在登录之后,每次请求进行拦截处理之后,通过token从数据库中查询session信息,将session信息维护到上下文中,利用ThreadLocal进行 全局 线程变量管理,并将上下文信息放入ThreadLocal中,也就是内存中缓存起来,这样可以提高我们对热点数据(频繁操作的数据)进行高速访问:内存速度是磁盘速度的500-1000倍。
1.3 权限验证方案
- 小型项目:在后台,超级管理员可以设置权限组作为一种角色,当其他管理员被创建的时候可以选择某一种角色。
- 大型项目(套餐):在平台的后台,平台超级管理员可以创建权限套餐,店铺超级管理员可以在店铺后台通过套餐范围内的权限分配给其他账号。
我们这里采取小型项目的解决思路来进行设计。
- 设置权限类型枚举
- 设置权限注解,作用在方法或类上
- 在拦截器登录认证之后进行权限验证处理
1.4 登录认证
- 设置登录的用户类型枚举
- 设置session注解,作用在方法或类上
- 在拦截器中进行登录认证处理
二、Session存储方案:上下文Context
- Session是包含token信息和adminId的,用于做
- 登录验证
- 包装Context
2.1 session体系
AdminSession
当前用户的AdminSession存放着重要的用于包装Context的信息
private Long id;
// 用于获取admin
private Long adminId;
// 用于存储token
private String token;
// 用于记录当前登录时间
private Long signinAt;
// 用于记录token过期时间
private Long expireAt;
当然,AdminSession这些属性并不能满足我们的需求,因此,我们需要对该类进行扩展。
这里,我们使用Wrapper类对其进行包装扩展
AdminSessionWrapper
// AdminSession信息
private AdminSession adminSession;
// Admin信息
private Admin admin;
// Role信息
private Role role;
SessionWrapper
SessionWrapper作为该体系最上层抽象接口,实现了不同SessionWrapper(比如AdminSessionWrapper)的统一管理。
2.2 Context体系
Context是用来在登录之后,对当前线程的session信息进行管理,并放置在全局中,这样我们可以在任何地方访问这些信息。因为Context包含了当前用户的登录信息和个人信息等基本信息,因此当我们在修改个人信息、查询个人信息等等操作变得非常简单。
Context
Context内部维护了一个SessionWrapper。
Contexts
Contexts是Context的管理类,内部维护了一个SessionThreadLocal。我们要想理解这个类,首先要理解ThreadLocal。
SessionThreadLocal
SessionThreadLocal继承了ThreadLocal,并把自己作为一个单例维护在类中,因此我们可以将该类理解为ThreadLocal。
ThreadLocal
ThreadLocal是对线程变量全局管理的一种实现。
通过查看源码可以看到,其内部维护了一个ThreadLocalMap
ThreadLocalMap是ThreadLocal的内部类,其实他内部维护了一个Entry数组,用来存储线程变量,并把线程作为key,变量作为value进行全局管理。
当我们调用set方法时候
实际上,就是把当前线程作为key,存入的值作为value进行存储的。调用get方法的时候,其实就是获取当前线程的变量。
我们完成了上下文的体系分析,那么我们来总结一下。
- SessionThreadLocal实际上是一个ThreadLocal,对线程变量进行全局管理。
- Contexts:用于管理SessionThreadLocal
- Context:内部维护了SessionWrapper信息,我们将一些需要的信息存入其中,再作为线程变量,通过Contexts set进入SessionThreadLocal中。
三、登录功能
- 效验数据:验证账号密码是否正确
- 写session:提供我们在项目的任何地方
- 生成并设置token:创建令牌
- 存储session到数据库
- 获取role:获取当前用户的role
- 封装sessionWrapper
3.1 效验数据
略过。。。
3.2 写Session
//利用下面这个方法生成一个64位token
String token = StringUtils.randomAlphanumeric(64);