文章目录
1.技术选型
1.网址
https://sa-token.cc/doc.html#/
2.Sa-Token介绍
Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。
3.Sa-Token 功能一览
Sa-Token 目前主要五大功能模块:登录认证、权限认证、单点登录、OAuth2.0、微服务鉴权。
- 登录认证 —— 单端登录、多端登录、同端互斥登录、七天内免登录。
- 权限认证 —— 权限认证、角色认证、会话二级认证。
- 踢人下线 —— 根据账号id踢人下线、根据Token值踢人下线。
- 注解式鉴权 —— 优雅的将鉴权与业务代码分离。
- 路由拦截式鉴权 —— 根据路由拦截鉴权,可适配 restful 模式。
- Session会话 —— 全端共享Session,单端独享Session,自定义Session,方便的存取值。
- 持久层扩展 —— 可集成 Redis,重启数据不丢失。
- 前后台分离 —— APP、小程序等不支持 Cookie 的终端也可以轻松鉴权。
- Token风格定制 —— 内置六种 Token 风格,还可:自定义 Token 生成策略。
- 记住我模式 —— 适配 [记住我] 模式,重启浏览器免验证。
- 二级认证 —— 在已登录的基础上再次认证,保证安全性。
- 模拟他人账号 —— 实时操作任意用户状态数据。
- 临时身份切换 —— 将会话身份临时切换为其它账号。
- 同端互斥登录 —— 像QQ一样手机电脑同时在线,但是两个手机上互斥登录。
- 账号封禁 —— 登录封禁、按照业务分类封禁、按照处罚阶梯封禁。
- 密码加密 —— 提供基础加密算法,可快速 MD5、SHA1、SHA256、AES 加密。
- 会话查询 —— 提供方便灵活的会话查询接口。
- Http Basic认证 —— 一行代码接入 Http Basic、Digest 认证。
- 全局侦听器 —— 在用户登陆、注销、被踢下线等关键性操作时进行一些AOP操作。
- 全局过滤器 —— 方便的处理跨域,全局设置安全响应头等操作。
- 多账号体系认证 —— 一个系统多套账号分开鉴权(比如商城的 User 表和 Admin 表)
- 单点登录 —— 内置三种单点登录模式:同域、跨域、同Redis、跨Redis、前后端分离等架构都可以搞定。
- 单点注销 —— 任意子系统内发起注销,即可全端下线。
- OAuth2.0认证 —— 轻松搭建 OAuth2.0 服务,支持openid模式 。
- 分布式会话 —— 提供共享数据中心分布式会话方案。
- 微服务网关鉴权 —— 适配Gateway、ShenYu、Zuul等常见网关的路由拦截认证。
- RPC调用鉴权 —— 网关转发鉴权,RPC调用鉴权,让服务调用不再裸奔
- 临时Token认证 —— 解决短时间的 Token 授权问题。
- 独立Redis —— 将权限缓存与业务缓存分离。
- Quick快速登录认证 —— 为项目零代码注入一个登录页面。
- 标签方言 —— 提供 Thymeleaf 标签方言集成包,提供 beetl 集成示例。
- jwt集成 —— 提供三种模式的 jwt 集成方案,提供 token 扩展参数能力。
- RPC调用状态传递 —— 提供 dubbo、grpc 等集成包,在RPC调用时登录状态不丢失。
- 参数签名 —— 提供跨系统API调用签名校验模块,防参数篡改,防请求重放。
- 自动续签 —— 提供两种Token过期策略,灵活搭配使用,还可自动续签。
- 开箱即用 —— 提供SpringMVC、WebFlux、Solon 等常见框架集成包,开箱即用。
- 最新技术栈 —— 适配最新技术栈:支持 SpringBoot 3.x,jdk 17。
2.鉴权数据模型设计
1.数据模型图
2.SQL
1.用户信息表
-- auto-generated definition create table auth_user ( id bigint auto_increment comment '主键' primary key, user_name varchar(32) null comment '用户名称/账号', nick_name varchar(32) null comment '昵称', email varchar(32) null comment '邮箱', phone varchar(32) null comment '手机号', password varchar(64) null comment '密码', sex tinyint(2) null comment '性别', avatar varchar(255) null comment '头像', status tinyint(2) null comment '状态 0启用 1禁用', introduce varchar(255) null comment '个人介绍', ext_json varchar(255) null comment '特殊字段', created_by varchar(32) null comment '创建人', created_time datetime null comment '创建时间', update_by varchar(32) null comment '更新人', update_time datetime null comment '更新时间', is_deleted int default 0 null comment '是否被删除 0未删除 1已删除' ) comment '用户信息表' charset = utf8;
2.角色表
-- auto-generated definition create table auth_role ( id bigint auto_increment primary key, role_name varchar(32) null comment '角色名称', role_key varchar(64) null comment '角色唯一标识', created_by varchar(32) null comment '创建人', created_time datetime null comment '创建时间', update_by varchar(32) null comment '更新人', update_time datetime null comment '更新时间', is_deleted int default 0 null comment '是否被删除 0未删除 1已删除' ) charset = utf8;
3.用户角色表(关联表)
-- auto-generated definition create table auth_user_role ( id bigint auto_increment comment '主键' primary key, user_id bigint null comment '用户id', role_id bigint null comment '角色id', created_by varchar(32) null comment '创建人', created_time datetime null comment '创建时间', update_by varchar(32) null comment '更新人', update_time datetime null comment '更新时间', is_deleted int default 0 null ) comment '用户角色表' charset = utf8;
4.权限表
-- auto-generated definition create table auth_permission ( id bigint auto_increment primary key, name varchar(64) null comment '权限名称', parent_id bigint null comment '父id', type tinyint null comment '权限类型 0菜单 1操作', menu_url varchar(255) null comment '菜单路由', status tinyint(2) null comment '状态 0启用 1禁用', `show` tinyint(2) null comment '展示状态 0展示 1隐藏', icon varchar(128) null comment '图标', permission_key varchar(64) null comment '权限唯一标识', created_by varchar(32) null comment '创建人', created_time datetime null comment '创建时间', update_by varchar(32) null comment '更新人', update_time datetime null comment '更新时间', is_deleted int default 0 null comment '是否被删除 0为删除 1已删除' ) charset = utf8;
5.角色权限表(关联表)
-- auto-generated definition create table auth_role_permission ( id bigint auto_increment primary key, role_id bigint null comment '角色id', permission_id bigint null comment '权限id', created_by varchar(32) null comment '创建人', created_time datetime null comment '创建时间', update_by varchar(32) null comment '更新人', update_time datetime null comment '更新时间', is_deleted int default 0 null ) comment '角色权限关联表' charset = utf8;
3.E-R图
3.鉴权微服务架构设计
1.新建一个鉴权模块
2.架构图
3.功能设计
1.用户基础模块
- 新增用户
- 修改用户
- 删除用户
- 用户启用
- 用户禁用
- 用户密码加密
2.角色基础模块
- 新增角色
- 修改角色
- 删除角色
- 角色与用户的关联
3.权限基础模块
- 新增权限
- 修改权限
- 删除权限
- 权限禁用与启用
- 权限的展示与隐藏
- 权限与角色关联
4.登录注册模块
注册用户与验证
1、短信的方式,通过向手机号发送验证码,来实现用户的验证并登录(考虑的成本是短信的费用)
2、邮箱的注册登录。
用户注册的时候,留一个邮箱,我们往邮箱里通过邮箱服务器发送一个链接,用户点击之后,实现一个激活,激活成功之后就完成了注册。(0 成本,坏处这种发送的邮件很容易进垃圾箱)
3、个人公众号模式(个人开发者无公司的,比较适合使用,0 成本)
用户登录的时候,弹出我们的这个公众号的码。扫码后,用户输入我们提示的验证码。可以随机比如说 nadbuge,通过我们的公众号对接的回调。能拿到一定的信息,用户的 openId。进而记录用户的信息
4、企业的服务号(必须要有营业执照,自己玩的不上线的话,也可以用测试号)
好处就是不仅打通了各种回调,而且还能拿到用户的信息。
登录功能
传统的 pc 形式,都是登录之后,写入 cookie。前端再次请求的时候,带着 cookie 一个身份识别就可以完成认证。坏处是什么?小程序呀,app 呀,其实是没有 cookie 这个概念的。为了更好的扩展,我们就直接选择 token的模式。token 放入 header 来实现用户身份的识别与鉴权。
5.踢人下线
发现风险用户,可以通过后台直接把用户踢掉,禁止其再访问,token 也可以直接置为失效的形式。
6.集成 redis
如果说我们选择了 token,然后不做 token 的保存,服务重启呀,分布式微服务啊,数据是无法共享并且会产生丢失问题,所以用 redis 来存储一些信息,实现共享。
7.自定义我们的 token 风格和前缀
- 比如正常的 token 可能是 uuid,我们可以选择其他形式
- 然后就是 token 的前端的传递,也可以去定义前缀,固定前缀才生效。
8.记住我
- 当我们去勾选记住我的时候,下次登录就自动实现了。
- 前后端分离,没有 token 的时候,必然会产生无法实现的问题,我们就选择在前端的 localstorage 来做。
9.网关统一鉴权
校验权限,校验用户的角色等等的东西,我们就放在网关里面统一去做。
不放在网关,导致我们的每个微服务,全要引入的鉴权的框架,不断的去写重复的代码。
数据的权限获取产生问题:
1、网关直接对接数据库,实现查询
2、redis 中获取数据,获取不到的时候还是要像第一种一样去数据库里查。
3、redis 中获取缓存,没有的话,从 auth 服务里面获取相关的信息。
4、直接从 redis 读取。