当前位置:首页 > 科技  > 软件

再见,Shiro !你好,Sa-Token!

来源: 责编: 时间:2023-11-30 09:30:30 185观看
导读Sa-Token 介绍Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。Sa-Token 旨在以简单、优雅的方式完成系统的权

Sa-Token 介绍

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。BFT28资讯网——每日最新资讯28at.com

Sa-Token 旨在以简单、优雅的方式完成系统的权限认证部分,以登录认证为例,你只需要:BFT28资讯网——每日最新资讯28at.com

// 会话登录,参数填登录人的账号id StpUtil.login(10001);

无需实现任何接口,无需创建任何配置文件,只需要这一句静态代码的调用,便可以完成会话登录认证。BFT28资讯网——每日最新资讯28at.com

如果一个接口需要登录后才能访问,我们只需调用以下代码:BFT28资讯网——每日最新资讯28at.com

// 校验当前客户端是否已经登录,如果未登录则抛出 `NotLoginException` 异常StpUtil.checkLogin();

在 Sa-Token 中,大多数功能都可以一行代码解决:BFT28资讯网——每日最新资讯28at.com

踢人下线:BFT28资讯网——每日最新资讯28at.com

// 将账号id为 10077 的会话踢下线 StpUtil.kickout(10077);

权限认证:BFT28资讯网——每日最新资讯28at.com

// 注解鉴权:只有具备 `user:add` 权限的会话才可以进入方法@SaCheckPermission("user:add")    public String insert(SysUser user) {    // ...     return "用户增加";}

路由拦截鉴权:BFT28资讯网——每日最新资讯28at.com

// 根据路由划分模块,不同模块不同鉴权 registry.addInterceptor(new SaInterceptor(handler -> {    SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));    SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));    SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));    SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));    SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice"));    // 更多模块... })).addPathPatterns("/**");

当你受够 Shiro、SpringSecurity 等框架的三拜九叩之后,你就会明白,相对于这些传统老牌框架,Sa-Token 的 API 设计是多么的简单、优雅!BFT28资讯网——每日最新资讯28at.com

Sa-Token 功能一览

Sa-Token 目前主要五大功能模块:登录认证、权限认证、单点登录、OAuth2.0、微服务鉴权。BFT28资讯网——每日最新资讯28at.com

  • 登录认证 —— 单端登录、多端登录、同端互斥登录、七天内免登录
  • 权限认证 —— 权限认证、角色认证、会话二级认证
  • Session会话 —— 全端共享Session、单端独享Session、自定义Session
  • 踢人下线 —— 根据账号id踢人下线、根据Token值踢人下线
  • 账号封禁 —— 登录封禁、按照业务分类封禁、按照处罚阶梯封禁
  • 持久层扩展 —— 可集成Redis、Memcached等专业缓存中间件,重启数据不丢失
  • 分布式会话 —— 提供jwt集成、共享数据中心两种分布式会话方案
  • 微服务网关鉴权 —— 适配Gateway、ShenYu、Zuul等常见网关的路由拦截认证
  • 单点登录 —— 内置三种单点登录模式:无论是否跨域、是否共享Redis,都可以搞定
  • OAuth2.0认证 —— 轻松搭建 OAuth2.0 服务,支持openid模式
  • 二级认证 —— 在已登录的基础上再次认证,保证安全性
  • Basic认证 —— 一行代码接入 Http Basic 认证
  • 独立Redis —— 将权限缓存与业务缓存分离
  • 临时Token认证 —— 解决短时间的Token授权问题
  • 模拟他人账号 —— 实时操作任意用户状态数据
  • 临时身份切换 —— 将会话身份临时切换为其它账号
  • 前后台分离 —— APP、小程序等不支持Cookie的终端
  • 同端互斥登录 —— 像QQ一样手机电脑同时在线,但是两个手机上互斥登录
  • 多账号认证体系 —— 比如一个商城项目的user表和admin表分开鉴权
  • Token风格定制 —— 内置六种Token风格,还可:自定义Token生成策略、自定义Token前缀
  • 注解式鉴权 —— 优雅的将鉴权与业务代码分离
  • 路由拦截式鉴权 —— 根据路由拦截鉴权,可适配restful模式
  • 自动续签 —— 提供两种Token过期策略,灵活搭配使用,还可自动续签
  • 会话治理 —— 提供方便灵活的会话查询接口
  • 记住我模式 —— 适配[记住我]模式,重启浏览器免验证
  • 密码加密 —— 提供密码加密模块,可快速MD5、SHA1、SHA256、AES、RSA加密
  • 全局侦听器 —— 在用户登陆、注销、被踢下线等关键性操作时进行一些AOP操作
  • 开箱即用 —— 提供SpringMVC、WebFlux等常见web框架starter集成包,真正的开箱即用

SpringBoot 集成 Sa-Token

一、添加maven依赖

<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc --><dependency>  <groupId>cn.dev33</groupId>  <artifactId>sa-token-spring-boot-starter</artifactId>  <version>1.34.0</version></dependency>

注:如果你使用的 SpringBoot 3.x,只需要将 sa-token-spring-boot-starter 修改为 sa-token-spring-boot3-starter 即可。BFT28资讯网——每日最新资讯28at.com

二、设置配置文件

你可以零配置启动项目 ,但同时你也可以在 application.yml 中增加如下配置,定制性使用框架:BFT28资讯网——每日最新资讯28at.com

server:    # 端口    port: 8081############## Sa-Token 配置 (文档: https://sa-token.cc) ##############sa-token:     # token名称 (同时也是cookie名称)    token-name: satoken    # token有效期,单位s 默认30天, -1代表永不过期     timeout: 2592000    # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒    activity-timeout: -1    # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)     is-concurrent: true    # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)     is-share: true    # token风格    token-style: uuid    # 是否输出操作日志     is-log: false

三、创建案例

@RestController    @RequestMapping("/user/")    public class UserController {        // 测试登录,浏览器访问:http://localhost:8081/user/doLogin?username=zhang&password=123456        @RequestMapping("doLogin")        public String doLogin(String username, String password) {            // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对             if("iron".equals(username) && "123456".equals(password)) {                StpUtil.login(10001);                return "登录成功";            }            return "登录失败";        }        // 查询登录状态,浏览器访问:http://localhost:8081/user/isLogin        @RequestMapping("isLogin")        public String isLogin() {            return "当前会话是否登录:" + StpUtil.isLogin();        }    }

登录认证

设计思路

对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验:BFT28资讯网——每日最新资讯28at.com

  • 如果校验通过,则:正常返回数据。
  • 如果校验未通过,则:抛出异常,告知其需要先进行登录。

那么,判断会话是否登录的依据是什么?我们先来简单分析一下登录访问流程:BFT28资讯网——每日最新资讯28at.com

  1. 用户提交 name + password 参数,调用登录接口。
  2. 登录成功,返回这个用户的 Token 会话凭证。
  3. 用户后续的每次请求,都携带上这个 Token。
  4. 服务器根据 Token 判断此会话是否登录成功。

所谓登录认证,指的就是服务器校验账号密码,为用户颁发 Token 会话凭证的过程,这个 Token 也是我们后续判断会话是否登录的关键所在。BFT28资讯网——每日最新资讯28at.com

登录与注销

根据以上思路,我们需要一个会话登录的函数:BFT28资讯网——每日最新资讯28at.com

// 会话登录:参数填写要登录的账号id,建议的数据类型:long | int | String, 不可以传入复杂类型,如:User、Admin 等等StpUtil.login(Object id);

只此一句代码,便可以使会话登录成功,实际上,Sa-Token 在背后做了大量的工作,包括但不限于:BFT28资讯网——每日最新资讯28at.com

  1. 检查此账号是否之前已有登录
  2. 为账号生成 Token 凭证与 Session 会话
  3. 通知全局侦听器,xx 账号登录成功
  4. 将 Token 注入到请求上下文
  5. 等等其它工作……

你暂时不需要完整的了解整个登录过程,你只需要记住关键一点:Sa-Token 为这个账号创建了一个Token凭证,且通过 Cookie 上下文返回给了前端。BFT28资讯网——每日最新资讯28at.com

所以一般情况下,我们的登录接口代码,会大致类似如下:BFT28资讯网——每日最新资讯28at.com

// 会话登录接口 @RequestMapping("doLogin")    public SaResult doLogin(String name, String pwd) {    // 第一步:比对前端提交的账号名称、密码    if("iron".equals(name) && "123456".equals(pwd)) {        // 第二步:根据账号id,进行登录         StpUtil.login(10001);        return SaResult.ok("登录成功");    }    return SaResult.error("登录失败");}

如果你对以上代码阅读没有压力,你可能会注意到略显奇怪的一点:此处仅仅做了会话登录,但并没有主动向前端返回 Token 信息。是因为不需要吗?严格来讲是需要的,只不过 StpUtil.login(id) 方法利用了 Cookie 自动注入的特性,省略了你手写返回 Token 的代码。BFT28资讯网——每日最新资讯28at.com

如果你对 Cookie 功能还不太了解,也不用担心,我们会在之后的 [ 前后端分离 ] 章节中详细的阐述 Cookie 功能,现在你只需要了解最基本的两点:BFT28资讯网——每日最新资讯28at.com

  • Cookie 可以从后端控制往浏览器中写入 Token 值。
  • Cookie 会在前端每次发起请求时自动提交 Token 值。

因此,在 Cookie 功能的加持下,我们可以仅靠 StpUtil.login(id) 一句代码就完成登录认证。BFT28资讯网——每日最新资讯28at.com

除了登录方法,我们还需要:BFT28资讯网——每日最新资讯28at.com

// 当前会话注销登录StpUtil.logout();// 获取当前会话是否已经登录,返回true=已登录,false=未登录StpUtil.isLogin();// 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`StpUtil.checkLogin();

异常 NotLoginException 代表当前会话暂未登录,可能的原因有很多:前端没有提交 Token、前端提交的 Token 是无效的、前端提交的 Token 已经过期 …… 等等,可参照此篇:未登录场景值,了解如何获取未登录的场景值。BFT28资讯网——每日最新资讯28at.com

会话查询

// 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException`StpUtil.getLoginId();// 类似查询API还有:StpUtil.getLoginIdAsString();    // 获取当前会话账号id, 并转化为`String`类型StpUtil.getLoginIdAsInt();       // 获取当前会话账号id, 并转化为`int`类型StpUtil.getLoginIdAsLong();      // 获取当前会话账号id, 并转化为`long`类型// ---------- 指定未登录情形下返回的默认值 ----------// 获取当前会话账号id, 如果未登录,则返回null StpUtil.getLoginIdDefaultNull();// 获取当前会话账号id, 如果未登录,则返回默认值 (`defaultValue`可以为任意类型)StpUtil.getLoginId(T defaultValue);

Token 查询

// 获取当前会话的token值StpUtil.getTokenValue();// 获取当前`StpLogic`的token名称StpUtil.getTokenName();// 获取指定token对应的账号id,如果未登录,则返回 nullStpUtil.getLoginIdByToken(String tokenValue);// 获取当前会话剩余有效期(单位:s,返回-1代表永久有效)StpUtil.getTokenTimeout();// 获取当前会话的token信息参数StpUtil.getTokenInfo();

有关TokenInfo参数详解,请参考:TokenInfo参数详解BFT28资讯网——每日最新资讯28at.com

来个小测试,加深一下理解

新建 LoginController,复制以下代码BFT28资讯网——每日最新资讯28at.com

/** * 登录测试  */@RestController@RequestMapping("/acc/")public class LoginController {    // 测试登录  ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456    @RequestMapping("doLogin")    public SaResult doLogin(String name, String pwd) {        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对         if("iron".equals(name) && "123456".equals(pwd)) {            StpUtil.login(10001);            return SaResult.ok("登录成功");        }        return SaResult.error("登录失败");    }    // 查询登录状态  ---- http://localhost:8081/acc/isLogin    @RequestMapping("isLogin")    public SaResult isLogin() {        return SaResult.ok("是否登录:" + StpUtil.isLogin());    }    // 查询 Token 信息  ---- http://localhost:8081/acc/tokenInfo    @RequestMapping("tokenInfo")    public SaResult tokenInfo() {        return SaResult.data(StpUtil.getTokenInfo());    }    // 测试注销  ---- http://localhost:8081/acc/logout    @RequestMapping("logout")    public SaResult logout() {        StpUtil.logout();        return SaResult.ok();    }}

权限认证

设计思路

所谓权限认证,核心逻辑就是判断一个账号是否拥有指定权限:BFT28资讯网——每日最新资讯28at.com

  • 有,就让你通过。
  • 没有?那么禁止访问!

深入到底层数据中,就是每个账号都会拥有一个权限码集合,框架来校验这个集合中是否包含指定的权限码。BFT28资讯网——每日最新资讯28at.com

例如:当前账号拥有权限码集合 ["user-add", "user-delete", "user-get"],这时候我来校验权限 "user-update",则其结果就是:验证失败,禁止访问。BFT28资讯网——每日最新资讯28at.com

所以现在问题的核心就是:BFT28资讯网——每日最新资讯28at.com

  1. 如何获取一个账号所拥有的的权限码集合?
  2. 本次操作需要验证的权限码是哪个?

获取当前账号权限码集合

因为每个项目的需求不同,其权限设计也千变万化,因此 [ 获取当前账号权限码集合 ] 这一操作不可能内置到框架中, 所以 Sa-Token 将此操作以接口的方式暴露给你,以方便你根据自己的业务逻辑进行重写。BFT28资讯网——每日最新资讯28at.com

你需要做的就是新建一个类,实现 StpInterface接口,例如以下代码:BFT28资讯网——每日最新资讯28at.com

/** * 自定义权限验证接口扩展 */@Component    // 保证此类被SpringBoot扫描,完成Sa-Token的自定义权限验证扩展 public class StpInterfaceImpl implements StpInterface {    /**     * 返回一个账号所拥有的权限码集合      */    @Override    public List<String> getPermissionList(Object loginId, String loginType) {        // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限        List<String> list = new ArrayList<String>();            list.add("101");        list.add("user.add");        list.add("user.update");        list.add("user.get");        // list.add("user.delete");        list.add("art.*");        return list;    }    /**     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)     */    @Override    public List<String> getRoleList(Object loginId, String loginType) {        // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色        List<String> list = new ArrayList<String>();            list.add("admin");        list.add("super-admin");        return list;    }}

参数解释:BFT28资讯网——每日最新资讯28at.com

  • loginId:账号id,即你在调用 StpUtil.login(id) 时写入的标识值。
  • loginType:账号体系标识,此处可以暂时忽略,在 [ 多账户认证 ] 章节下会对这个概念做详细的解释。

可参考代码:码云:StpInterfaceImpl.javaBFT28资讯网——每日最新资讯28at.com

注意: StpInterface 接口在需要鉴权时由框架自动调用,开发者只需要配置好就可以使用下面的鉴权方法或后面的注解鉴权BFT28资讯网——每日最新资讯28at.com

权限校验

然后就可以用以下api来鉴权了BFT28资讯网——每日最新资讯28at.com

// 获取:当前账号所拥有的权限集合StpUtil.getPermissionList();// 判断:当前账号是否含有指定权限, 返回 true 或 falseStpUtil.hasPermission("user.add");        // 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException StpUtil.checkPermission("user.add");        // 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过]StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get");        // 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]StpUtil.checkPermissionOr("user.add", "user.delete", "user.get");

扩展:NotPermissionException 对象可通过 getLoginType() 方法获取具体是哪个 StpLogic 抛出的异常BFT28资讯网——每日最新资讯28at.com

角色校验

在Sa-Token中,角色和权限可以独立验证BFT28资讯网——每日最新资讯28at.com

// 获取:当前账号所拥有的角色集合StpUtil.getRoleList();// 判断:当前账号是否拥有指定角色, 返回 true 或 falseStpUtil.hasRole("super-admin");        // 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleExceptionStpUtil.checkRole("super-admin");        // 校验:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过]StpUtil.checkRoleAnd("super-admin", "shop-admin");        // 校验:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] StpUtil.checkRoleOr("super-admin", "shop-admin");

扩展:NotRoleException 对象可通过 getLoginType() 方法获取具体是哪个 StpLogic 抛出的异常BFT28资讯网——每日最新资讯28at.com

权限通配符

Sa-Token允许你根据通配符指定泛权限,例如当一个账号拥有art.*的权限时,art.add、art.delete、art.update都将匹配通过BFT28资讯网——每日最新资讯28at.com

// 当拥有 art.* 权限时StpUtil.hasPermission("art.add");        // trueStpUtil.hasPermission("art.update");     // trueStpUtil.hasPermission("goods.add");      // false// 当拥有 *.delete 权限时StpUtil.hasPermission("art.delete");      // trueStpUtil.hasPermission("user.delete");     // trueStpUtil.hasPermission("user.update");     // false// 当拥有 *.js 权限时StpUtil.hasPermission("index.js");        // trueStpUtil.hasPermission("index.css");       // falseStpUtil.hasPermission("index.html");      // false

上帝权限:当一个账号拥有 "*" 权限时,他可以验证通过任何权限码 (角色认证同理)BFT28资讯网——每日最新资讯28at.com

如何把权限精确到按钮级?

权限精确到按钮级的意思就是指:权限范围可以控制到页面上的每一个按钮是否显示。BFT28资讯网——每日最新资讯28at.com

思路:如此精确的范围控制只依赖后端已经难以完成,此时需要前端进行一定的逻辑判断。BFT28资讯网——每日最新资讯28at.com

如果是前后端一体项目,可以参考:Thymeleaf 标签方言,如果是前后端分离项目,则:BFT28资讯网——每日最新资讯28at.com

  1. 在登录时,把当前账号拥有的所有权限码一次性返回给前端。
  2. 前端将权限码集合保存在localStorage或其它全局状态管理对象中。
  3. 在需要权限控制的按钮上,使用 js 进行逻辑判断,例如在Vue框架中我们可以使用如下写法:
<button v-if="arr.indexOf('user.delete') > -1">删除按钮</button>

其中:arr是当前用户拥有的权限码数组,user.delete是显示按钮需要拥有的权限码,删除按钮是用户拥有权限码才可以看到的内容。BFT28资讯网——每日最新资讯28at.com

注意:以上写法只为提供一个参考示例,不同框架有不同写法,大家可根据项目技术栈灵活封装进行调用。BFT28资讯网——每日最新资讯28at.com

踢人下线

所谓踢人下线,核心操作就是找到指定 loginId 对应的 Token,并设置其失效。BFT28资讯网——每日最新资讯28at.com

强制注销

StpUtil.logout(10001);                    // 强制指定账号注销下线 StpUtil.logout(10001, "PC");              // 强制指定账号指定端注销下线 StpUtil.logoutByTokenValue("token");      // 强制指定 Token 注销下线

踢人下线

StpUtil.kickout(10001);                    // 将指定账号踢下线 StpUtil.kickout(10001, "PC");              // 将指定账号指定端踢下线StpUtil.kickoutByTokenValue("token");      // 将指定 Token 踢下线

强制注销 和 踢人下线 的区别在于:BFT28资讯网——每日最新资讯28at.com

  • 强制注销等价于对方主动调用了注销方法,再次访问会提示:Token无效。
  • 踢人下线不会清除Token信息,而是将其打上特定标记,再次访问会提示:Token已被踢下线。

注解鉴权

有同学表示:尽管使用代码鉴权非常方便,但是我仍希望把鉴权逻辑和业务逻辑分离开来,我可以使用注解鉴权吗?当然可以!BFT28资讯网——每日最新资讯28at.com

注解鉴权 —— 优雅的将鉴权与业务代码分离!BFT28资讯网——每日最新资讯28at.com

  • @SaCheckLogin: 登录校验 —— 只有登录之后才能进入该方法。
  • @SaCheckRole("admin"): 角色校验 —— 必须具有指定角色标识才能进入该方法。
  • @SaCheckPermission("user:add"): 权限校验 —— 必须具有指定权限才能进入该方法。
  • @SaCheckSafe: 二级认证校验 —— 必须二级认证之后才能进入该方法。
  • @SaCheckBasic: HttpBasic校验 —— 只有通过 Basic 认证后才能进入该方法。
  • @SaIgnore:忽略校验 —— 表示被修饰的方法或类无需进行注解鉴权和路由拦截器鉴权。
  • @SaCheckDisable("comment"):账号服务封禁校验 —— 校验当前账号指定服务是否被封禁。

Sa-Token 使用全局拦截器完成注解鉴权功能,为了不为项目带来不必要的性能负担,拦截器默认处于关闭状态因此,为了使用注解鉴权,你必须手动将 Sa-Token 的全局拦截器注册到你项目中BFT28资讯网——每日最新资讯28at.com

1、注册拦截器

以SpringBoot2.0为例,新建配置类SaTokenConfigure.javaBFT28资讯网——每日最新资讯28at.com

@Configurationpublic class SaTokenConfigure implements WebMvcConfigurer {    // 注册 Sa-Token 拦截器,打开注解式鉴权功能     @Override    public void addInterceptors(InterceptorRegistry registry) {        // 注册 Sa-Token 拦截器,打开注解式鉴权功能         registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");        }}

保证此类被springboot启动类扫描到即可BFT28资讯网——每日最新资讯28at.com

2、使用注解鉴权

然后我们就可以愉快的使用注解鉴权了:BFT28资讯网——每日最新资讯28at.com

// 登录校验:只有登录之后才能进入该方法 @SaCheckLogin                            @RequestMapping("info")    public String info() {    return "查询用户信息";}// 角色校验:必须具有指定角色才能进入该方法 @SaCheckRole("super-admin")            @RequestMapping("add")    public String add() {    return "用户增加";}// 权限校验:必须具有指定权限才能进入该方法 @SaCheckPermission("user-add")            @RequestMapping("add")    public String add() {    return "用户增加";}// 二级认证校验:必须二级认证之后才能进入该方法 @SaCheckSafe()            @RequestMapping("add")    public String add() {    return "用户增加";}// Http Basic 校验:只有通过 Basic 认证后才能进入该方法 @SaCheckBasic(account = "sa:123456")    @RequestMapping("add")    public String add() {    return "用户增加";}// 校验当前账号是否被封禁 comment 服务,如果已被封禁会抛出异常,无法进入方法 @SaCheckDisable("comment")                    @RequestMapping("send")    public String send() {    return "查询用户信息";}

注:以上注解都可以加在类上,代表为这个类所有方法进行鉴权BFT28资讯网——每日最新资讯28at.com

3、设定校验模式

@SaCheckRole与@SaCheckPermission注解可设置校验模式,例如:BFT28资讯网——每日最新资讯28at.com

// 注解式鉴权:只要具有其中一个权限即可通过校验 @RequestMapping("atJurOr")@SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR)        public SaResult atJurOr() {    return SaResult.data("用户信息");}

mode有两种取值:BFT28资讯网——每日最新资讯28at.com

  • SaMode.AND, 标注一组权限,会话必须全部具有才可通过校验。
  • SaMode.OR, 标注一组权限,会话只要具有其一即可通过校验。

4、角色权限双重 “or校验”

假设有以下业务场景:一个接口在具有权限 user.add 或角色 admin 时可以调通。怎么写?BFT28资讯网——每日最新资讯28at.com

// 角色权限双重 “or校验”:具备指定权限或者指定角色即可通过校验@RequestMapping("userAdd")@SaCheckPermission(value = "user.add", orRole = "admin")        public SaResult userAdd() {    return SaResult.data("用户信息");}

orRole 字段代表权限认证未通过时的次要选择,两者只要其一认证成功即可通过校验,其有三种写法:BFT28资讯网——每日最新资讯28at.com

  • 写法一:orRole = "admin",代表需要拥有角色 admin 。
  • 写法二:orRole = {"admin", "manager", "staff"},代表具有三个角色其一即可。
  • 写法三:orRole = {"admin, manager, staff"},代表必须同时具有三个角色。

5、忽略认证

使用 @SaIgnore 可表示一个接口忽略认证:BFT28资讯网——每日最新资讯28at.com

@SaCheckLogin@RestControllerpublic class TestController {    // ... 其它方法     // 此接口加上了 @SaIgnore 可以游客访问     @SaIgnore    @RequestMapping("getList")    public SaResult getList() {        // ...         return SaResult.ok();     }}

如上代码表示:TestController 中的所有方法都需要登录后才可以访问,但是 getList 接口可以匿名游客访问。BFT28资讯网——每日最新资讯28at.com

  • @SaIgnore 修饰方法时代表这个方法可以被游客访问,修饰类时代表这个类中的所有接口都可以游客访问。
  • @SaIgnore 具有最高优先级,当 @SaIgnore 和其它鉴权注解一起出现时,其它鉴权注解都将被忽略。
  • @SaIgnore 同样可以忽略掉 Sa-Token 拦截器中的路由鉴权,在下面的 [路由拦截鉴权] 章节中我们会讲到。

6、在业务逻辑层使用注解鉴权

疑问:我能否将注解写在其它架构层呢,比如业务逻辑层?BFT28资讯网——每日最新资讯28at.com

使用拦截器模式,只能在Controller层进行注解鉴权,如需在任意层级使用注解鉴权,请参考:AOP注解鉴权BFT28资讯网——每日最新资讯28at.com

自定义 Token 风格

自定义token前缀

sa-token:     # token前缀    token-prefix: Bearer

内置风格

Sa-Token默认的token生成策略是uuid风格,其模样类似于:623368f0-ae5e-4475-a53f-93e4225f16ae。如果你对这种风格不太感冒,还可以将token生成设置为其他风格。BFT28资讯网——每日最新资讯28at.com

怎么设置呢?只需要在yml配置文件里设置 sa-token.token-style=风格类型 即可,其有多种取值:BFT28资讯网——每日最新资讯28at.com

// 1. token-style=uuid    —— uuid风格 (默认风格)"623368f0-ae5e-4475-a53f-93e4225f16ae"// 2. token-style=simple-uuid    —— 同上,uuid风格, 只不过去掉了中划线"6fd4221395024b5f87edd34bc3258ee8"// 3. token-style=random-32    —— 随机32位字符串"qEjyPsEA1Bkc9dr8YP6okFr5umCZNR6W"// 4. token-style=random-64    —— 随机64位字符串"v4ueNLEpPwMtmOPMBtOOeIQsvP8z9gkMgIVibTUVjkrNrlfra5CGwQkViDjO8jcc"// 5. token-style=random-128    —— 随机128位字符串"nojYPmcEtrFEaN0Otpssa8I8jpk8FO53UcMZkCP9qyoHaDbKS6dxoRPky9c6QlftQ0pdzxRGXsKZmUSrPeZBOD6kJFfmfgiRyUmYWcj4WU4SSP2ilakWN1HYnIuX0Olj"// 6. token-style=tik    —— tik风格"gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__"

自定义 Token 生成策略

如果你觉着以上风格都不是你喜欢的类型,那么你还可以自定义token生成策略,来定制化token生成风格。BFT28资讯网——每日最新资讯28at.com

怎么做呢?只需要重写 SaStrategy 策略类的 createToken 算法即可:BFT28资讯网——每日最新资讯28at.com

参考步骤如下:

1、在SaTokenConfigure配置类中添加代码:BFT28资讯网——每日最新资讯28at.com

@Configurationpublic class SaTokenConfigure {    /**     * 重写 Sa-Token 框架内部算法策略      */    @Autowired    public void rewriteSaStrategy() {        // 重写 Token 生成策略         SaStrategy.me.createToken = (loginId, loginType) -> {            return SaFoxUtil.getRandomString(60);    // 随机60位长度字符串        };    }}

2、再次调用 StpUtil.login(10001)方法进行登录,观察其生成的token样式:BFT28资讯网——每日最新资讯28at.com

fuPSwZsnUhwgz08GTCH4wOgasWtc3odP4HLwXJ7NDGOximTvT4OlW19zeLHBFT28资讯网——每日最新资讯28at.com

集成JWT的Token风格

引入依赖

首先在项目已经引入 Sa-Token 的基础上,继续添加:BFT28资讯网——每日最新资讯28at.com

<!-- Sa-Token 整合 jwt --><dependency>  <groupId>cn.dev33</groupId>  <artifactId>sa-token-jwt</artifactId>  <version>1.34.0</version></dependency>

注意: sa-token-jwt 显式依赖 hutool-jwt 5.7.14 版本,意味着:你的项目中要么不引入 Hutool,要么引入版本 >= 5.7.14 的 Hutool 版本BFT28资讯网——每日最新资讯28at.com

配置密钥

在 application.yml 配置文件中配置 jwt 生成秘钥:BFT28资讯网——每日最新资讯28at.com

sa-token:    # jwt秘钥     jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk

注入jwt实现

根据不同的整合规则,插件提供了三种不同的模式,你需要 选择其中一种 注入到你的项目中BFT28资讯网——每日最新资讯28at.com

@Configurationpublic class SaTokenConfigure {    // Sa-Token 整合 jwt (Simple 简单模式)    @Bean    public StpLogic getStpLogicJwt() {        return new StpLogicJwtForSimple();    }     // Sa-Token 整合 jwt (Mixin 混入模式)    @Bean    public StpLogic getStpLogicJwt() {        return new StpLogicJwtForMixin();    }     // Sa-Token 整合 jwt (Stateless 无状态模式)    @Bean    public StpLogic getStpLogicJwt() {        return new StpLogicJwtForStateless();    }}

不同模式策略对比

注入不同模式会让框架具有不同的行为策略,以下是三种模式的差异点(为方便叙述,以下比较以同时引入 jwt 与 Redis 作为前提):BFT28资讯网——每日最新资讯28at.com

功能点BFT28资讯网——每日最新资讯28at.com

Simple 简单模式BFT28资讯网——每日最新资讯28at.com

Mixin 混入模式BFT28资讯网——每日最新资讯28at.com

Stateless 无状态模式BFT28资讯网——每日最新资讯28at.com

Token风格BFT28资讯网——每日最新资讯28at.com

jwt风格BFT28资讯网——每日最新资讯28at.com

jwt风格BFT28资讯网——每日最新资讯28at.com

jwt风格BFT28资讯网——每日最新资讯28at.com

登录数据存储BFT28资讯网——每日最新资讯28at.com

Redis中BFT28资讯网——每日最新资讯28at.com

Token中BFT28资讯网——每日最新资讯28at.com

Token中BFT28资讯网——每日最新资讯28at.com

Session存储BFT28资讯网——每日最新资讯28at.com

Redis中BFT28资讯网——每日最新资讯28at.com

Redis中BFT28资讯网——每日最新资讯28at.com

无SessionBFT28资讯网——每日最新资讯28at.com

注销下线BFT28资讯网——每日最新资讯28at.com

前后端双清数据BFT28资讯网——每日最新资讯28at.com

前后端双清数据BFT28资讯网——每日最新资讯28at.com

前端清除数据BFT28资讯网——每日最新资讯28at.com

踢人下线APIBFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

顶人下线APIBFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

登录认证BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

角色认证BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

权限认证BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

timeout 有效期BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

activity-timeout 有效期BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

id反查TokenBFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

会话管理BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

部分支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

注解鉴权BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

路由拦截鉴权BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

账号封禁BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

身份切换BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

二级认证BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

支持BFT28资讯网——每日最新资讯28at.com

模式总结BFT28资讯网——每日最新资讯28at.com

Token风格替换BFT28资讯网——每日最新资讯28at.com

jwt 与 Redis 逻辑混合BFT28资讯网——每日最新资讯28at.com

完全舍弃Redis,只用jwtBFT28资讯网——每日最新资讯28at.com

扩展参数

你可以通过以下方式在登录时注入扩展参数:BFT28资讯网——每日最新资讯28at.com

// 登录10001账号,并为生成的 Token 追加扩展参数nameStpUtil.login(10001, SaLoginConfig.setExtra("name", "zhangsan"));// 连缀写法追加多个StpUtil.login(10001, SaLoginConfig              .setExtra("name", "zhangsan")              .setExtra("age", 18)              .setExtra("role", "超级管理员"));// 获取扩展参数 String name = StpUtil.getExtra("name");// 获取任意 Token 的扩展参数 String name = StpUtil.getExtra("tokenValue", "name");

在多账户模式中集成 jwt

sa-token-jwt 插件默认只为 StpUtil 注入 StpLogicJwtFoxXxx 实现,自定义的 StpUserUtil 是不会自动注入的,我们需要帮其手动注入:BFT28资讯网——每日最新资讯28at.com

/** * 为 StpUserUtil 注入 StpLogicJwt 实现  */@Autowiredpublic void setUserStpLogic() {    StpUserUtil.setStpLogic(new StpLogicJwtForSimple(StpUserUtil.TYPE));}

自定义 SaJwtUtil 生成 token 的算法

如果需要自定义生成 token 的算法(例如更换sign方式),直接重写 SaJwtTemplate 对象即可:BFT28资讯网——每日最新资讯28at.com

/** * 自定义 SaJwtUtil 生成 token 的算法  */@Autowiredpublic void setSaJwtTemplate() {    SaJwtUtil.setSaJwtTemplate(new SaJwtTemplate() {        @Override        public String generateToken(JWT jwt, String keyt) {            System.out.println("------ 自定义了 token 生成算法");            return super.generateToken(jwt, keyt);        }    });}

注意点

1、使用 jwt-simple 模式后,is-share=false 恒等于 false。BFT28资讯网——每日最新资讯28at.com

is-share=true 的意思是每次登录都产生一样的 token,这种策略和 [ 为每个 token 单独设定 setExtra 数据 ] 不兼容的, 为保证正确设定 Extra 数据,当使用 jwt-simple 模式后,is-share 配置项 恒等于 false。BFT28资讯网——每日最新资讯28at.com

2、使用 jwt-mixin 模式后,is-concurrent 必须为 true。BFT28资讯网——每日最新资讯28at.com

is-concurrent=false 代表每次登录都把旧登录顶下线,但是 jwt-mixin 模式登录的 token 并不会记录在持久库数据中, 技术上来讲无法将其踢下线,所以此时顶人下线和踢人下线等 API 都属于不可用状态,所以此时 is-concurrent 配置项必须配置为 true。BFT28资讯网——每日最新资讯28at.com

全局侦听器

工作原理

Sa-Token 提供一种侦听器机制,通过注册侦听器,你可以订阅框架的一些关键性事件,例如:用户登录、退出、被踢下线等。BFT28资讯网——每日最新资讯28at.com

事件触发流程大致如下:BFT28资讯网——每日最新资讯28at.com

框架默认内置了侦听器 SaTokenListenerForLog 实现:代码参考 ,功能是控制台 log 打印输出,你可以通过配置sa-token.is-log=true开启。BFT28资讯网——每日最新资讯28at.com

要注册自定义的侦听器也非常简单:BFT28资讯网——每日最新资讯28at.com

  1. 新建类实现 SaTokenListener 接口。
  2. 将实现类注册到 SaTokenEventCenter 事件发布中心。

自定义侦听器实现

新建实现类:

新建MySaTokenListener.java,实现SaTokenListener接口,并添加上注解@Component,保证此类被SpringBoot扫描到:BFT28资讯网——每日最新资讯28at.com

/** * 自定义侦听器的实现  */@Componentpublic class MySaTokenListener implements SaTokenListener {    /** 每次登录时触发 */    @Override    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {        System.out.println("---------- 自定义侦听器实现 doLogin");    }    /** 每次注销时触发 */    @Override    public void doLogout(String loginType, Object loginId, String tokenValue) {        System.out.println("---------- 自定义侦听器实现 doLogout");    }    /** 每次被踢下线时触发 */    @Override    public void doKickout(String loginType, Object loginId, String tokenValue) {        System.out.println("---------- 自定义侦听器实现 doKickout");    }    /** 每次被顶下线时触发 */    @Override    public void doReplaced(String loginType, Object loginId, String tokenValue) {        System.out.println("---------- 自定义侦听器实现 doReplaced");    }    /** 每次被封禁时触发 */    @Override    public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {        System.out.println("---------- 自定义侦听器实现 doDisable");    }    /** 每次被解封时触发 */    @Override    public void doUntieDisable(String loginType, Object loginId, String service) {        System.out.println("---------- 自定义侦听器实现 doUntieDisable");    }    /** 每次二级认证时触发 */    @Override    public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {        System.out.println("---------- 自定义侦听器实现 doOpenSafe");    }    /** 每次退出二级认证时触发 */    @Override    public void doCloseSafe(String loginType, String tokenValue, String service) {        System.out.println("---------- 自定义侦听器实现 doCloseSafe");    }    /** 每次创建Session时触发 */    @Override    public void doCreateSession(String id) {        System.out.println("---------- 自定义侦听器实现 doCreateSession");    }    /** 每次注销Session时触发 */    @Override    public void doLogoutSession(String id) {        System.out.println("---------- 自定义侦听器实现 doLogoutSession");    }    /** 每次Token续期时触发 */    @Override    public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {        System.out.println("---------- 自定义侦听器实现 doRenewTimeout");    }}
2.2、将侦听器注册到事件中心:

以上代码由于添加了 @Component 注解,会被 SpringBoot 扫描并自动注册到事件中心,此时我们无需手动注册。BFT28资讯网——每日最新资讯28at.com

如果我们没有添加 @Component 注解或者项目属于非 IOC 自动注入环境,则需要我们手动将这个侦听器注册到事件中心:BFT28资讯网——每日最新资讯28at.com

// 将侦听器注册到事件发布中心SaTokenEventCenter.registerListener(new MySaTokenListener());

事件中心的其它一些常用方法:BFT28资讯网——每日最新资讯28at.com

// 获取已注册的所有侦听器 SaTokenEventCenter.getListenerList(); // 重置侦听器集合 SaTokenEventCenter.setListenerList(listenerList); // 注册一个侦听器 SaTokenEventCenter.registerListener(listener); // 注册一组侦听器 SaTokenEventCenter.registerListenerList(listenerList); // 移除一个侦听器 SaTokenEventCenter.removeListener(listener); // 移除指定类型的所有侦听器 SaTokenEventCenter.removeListener(cls); // 清空所有已注册的侦听器 SaTokenEventCenter.clearListener(); // 判断是否已经注册了指定侦听器  SaTokenEventCenter.hasListener(listener); // 判断是否已经注册了指定类型的侦听器   SaTokenEventCenter.hasListener(cls);
2.3、启动测试:

在 TestController 中添加登录测试代码:BFT28资讯网——每日最新资讯28at.com

// 测试登录接口 @RequestMapping("login")public SaResult login() {    System.out.println("登录前");    StpUtil.login(10001);            System.out.println("登录后");    return SaResult.ok();}

3、其它注意点

3.1、你可以通过继承SaTokenListenerForSimple快速实现一个侦听器:
@Componentpublic class MySaTokenListener extends SaTokenListenerForSimple {    /*     * SaTokenListenerForSimple 对所有事件提供了空实现,通过继承此类,你只需重写一部分方法即可实现一个可用的侦听器。     */    /** 每次登录时触发 */    @Override    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {        System.out.println("---------- 自定义侦听器实现 doLogin");    }}3.2、使用匿名内部类的方式注册:// 登录时触发 SaTokenEventCenter.registerListener(new SaTokenListenerForSimple() {    @Override    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {        System.out.println("---------------- doLogin");    }});
3.3、使用 try-catch 包裹不安全的代码:

如果你认为你的事件处理代码是不安全的(代码可能在运行时抛出异常),则需要使用 try-catch 包裹代码,以防因为抛出异常导致 Sa-Token 的整个登录流程被强制中断。BFT28资讯网——每日最新资讯28at.com

// 登录时触发 SaTokenEventCenter.registerListener(new SaTokenListenerForSimple() {    @Override    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {        try {            // 不安全代码需要写在 try-catch 里             // ......          } catch (Exception e) {            e.printStackTrace();        }    }});
3.4、疑问:一个项目可以注册多个侦听器吗?

可以,多个侦听器间彼此独立,互不影响,按照注册顺序依次接受到事件通知。BFT28资讯网——每日最新资讯28at.com

单点登录

技术选型:[ 单点登录 ] VS [ OAuth2.0 ]

功能点BFT28资讯网——每日最新资讯28at.com

SSO单点登录BFT28资讯网——每日最新资讯28at.com

OAuth2.0BFT28资讯网——每日最新资讯28at.com

统一认证BFT28资讯网——每日最新资讯28at.com

支持度高BFT28资讯网——每日最新资讯28at.com

支持度高BFT28资讯网——每日最新资讯28at.com

统一注销BFT28资讯网——每日最新资讯28at.com

支持度高BFT28资讯网——每日最新资讯28at.com

支持度低BFT28资讯网——每日最新资讯28at.com

多个系统会话一致性BFT28资讯网——每日最新资讯28at.com

强一致BFT28资讯网——每日最新资讯28at.com

弱一致BFT28资讯网——每日最新资讯28at.com

第三方应用授权管理BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

支持度高BFT28资讯网——每日最新资讯28at.com

自有系统授权管理BFT28资讯网——每日最新资讯28at.com

支持度高BFT28资讯网——每日最新资讯28at.com

支持度低BFT28资讯网——每日最新资讯28at.com

Client级的权限校验BFT28资讯网——每日最新资讯28at.com

不支持BFT28资讯网——每日最新资讯28at.com

支持度高BFT28资讯网——每日最新资讯28at.com

集成简易度BFT28资讯网——每日最新资讯28at.com

比较简单BFT28资讯网——每日最新资讯28at.com

难度中等BFT28资讯网——每日最新资讯28at.com

注:以上仅为在 Sa-Token 中两种技术的差异度比较,不同框架的实现可能略有差异,但整体思想是一致的。BFT28资讯网——每日最新资讯28at.com

SSO单点登录

什么是单点登录?解决什么问题?

举个场景,假设我们的系统被切割为N个部分:商城、论坛、直播、社交…… 如果用户每访问一个模块都要登录一次,那么用户将会疯掉, 为了优化用户体验,我们急需一套机制将这N个系统的认证授权互通共享,让用户在一个系统登录之后,便可以畅通无阻的访问其它所有系统。BFT28资讯网——每日最新资讯28at.com

单点登录——就是为了解决这个问题而生!BFT28资讯网——每日最新资讯28at.com

简而言之,单点登录可以做到:在多个互相信任的系统中,用户只需登录一次,就可以访问所有系统。BFT28资讯网——每日最新资讯28at.com

架构选型

Sa-Token-SSO 由简入难划分为三种模式,解决不同架构下的 SSO 接入问题:BFT28资讯网——每日最新资讯28at.com

系统架构BFT28资讯网——每日最新资讯28at.com

采用模式BFT28资讯网——每日最新资讯28at.com

简介BFT28资讯网——每日最新资讯28at.com

文档链接BFT28资讯网——每日最新资讯28at.com

前端同域 + 后端同 RedisBFT28资讯网——每日最新资讯28at.com

模式一BFT28资讯网——每日最新资讯28at.com

共享 Cookie 同步会话BFT28资讯网——每日最新资讯28at.com

文档BFT28资讯网——每日最新资讯28at.com

、示例BFT28资讯网——每日最新资讯28at.com

前端不同域 + 后端同 RedisBFT28资讯网——每日最新资讯28at.com

模式二BFT28资讯网——每日最新资讯28at.com

URL重定向传播会话BFT28资讯网——每日最新资讯28at.com

文档BFT28资讯网——每日最新资讯28at.com

、示例BFT28资讯网——每日最新资讯28at.com

前端不同域 + 后端不同 RedisBFT28资讯网——每日最新资讯28at.com

模式三BFT28资讯网——每日最新资讯28at.com

Http请求获取会话BFT28资讯网——每日最新资讯28at.com

文档BFT28资讯网——每日最新资讯28at.com

、示例BFT28资讯网——每日最新资讯28at.com

  1. 前端同域:就是指多个系统可以部署在同一个主域名之下,比如:c1.domain.com、c2.domain.com、c3.domain.com。
  2. 后端同Redis:就是指多个系统可以连接同一个Redis。PS:这里并不需要把所有项目的数据都放在同一个Redis中,Sa-Token提供了 [权限缓存与业务缓存分离] 的解决方案,详情戳:Alone独立Redis插件。
  3. 如果既无法做到前端同域,也无法做到后端同Redis,那么只能走模式三,Http请求获取会话(Sa-Token对SSO提供了完整的封装,你只需要按照示例从文档上复制几段代码便可以轻松集成)。

Sa-Token-SSO 特性

  1. API 简单易用,文档介绍详细,且提供直接可用的集成示例。
  2. 支持三种模式,不论是否跨域、是否共享Redis、是否前后端分离,都可以完美解决。
  3. 安全性高:内置域名校验、Ticket校验、秘钥校验等,杜绝Ticket劫持、Token窃取等常见攻击手段(文档讲述攻击原理和防御手段)。
  4. 不丢参数:笔者曾试验多个单点登录框架,均有参数丢失的情况,比如重定向之前是:http://a.com?id=1&name=2,登录成功之后就变成了:http://a.com?id=1,Sa-Token-SSO内有专门的算法保证了参数不丢失,登录成功之后原路返回页面。
  5. 无缝集成:由于Sa-Token本身就是一个权限认证框架,因此你可以只用一个框架同时解决权限认证 + 单点登录问题,让你不再到处搜索:xxx单点登录与xxx权限认证如何整合……
  6. 高可定制:Sa-Token-SSO模块对代码架构侵入性极低,结合Sa-Token本身的路由拦截特性,你可以非常轻松的定制化开发。

搭建统一认证中心 SSO-Server

添加maven依赖

<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc --><dependency>    <groupId>cn.dev33</groupId>    <artifactId>sa-token-spring-boot-starter</artifactId>    <version>1.34.0</version></dependency><!-- Sa-Token 插件:整合SSO --><dependency>    <groupId>cn.dev33</groupId>    <artifactId>sa-token-sso</artifactId>    <version>1.34.0</version></dependency><!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) --><dependency>    <groupId>cn.dev33</groupId>    <artifactId>sa-token-dao-redis-jackson</artifactId>    <version>1.34.0</version></dependency><dependency>    <groupId>org.apache.commons</groupId>    <artifactId>commons-pool2</artifactId></dependency><!-- 视图引擎(在前后端不分离模式下提供视图支持) --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- Http请求工具(在模式三的单点注销功能下用到,如不需要可以注释掉) --><dependency>    <groupId>com.dtflys.forest</groupId>    <artifactId>forest-spring-boot-starter</artifactId>    <version>1.5.26</version></dependency>

除了 sa-token-spring-boot-starter 和 sa-token-sso 以外,其它包都是可选的:BFT28资讯网——每日最新资讯28at.com

  • 在 SSO 模式三时 Redis 相关包是可选的
  • 在前后端分离模式下可以删除 thymeleaf 相关包
  • 在不需要 SSO 模式三单点注销的情况下可以删除 http 工具包

建议先完整测试三种模式之后再对pom依赖进行酌情删减。BFT28资讯网——每日最新资讯28at.com

开放认证接口

/** * Sa-Token-SSO Server端 Controller  */@RestControllerpublic class SsoServerController {    /*     * SSO-Server端:处理所有SSO相关请求 (下面的章节我们会详细列出开放的接口)      */    @RequestMapping("/sso/*")    public Object ssoRequest() {        return SaSsoProcessor.instance.serverDister();    }    /**     * 配置SSO相关参数      */    @Autowired    private void configSso(SaSsoConfig sso) {        // 配置:未登录时返回的View         sso.setNotLoginView(() -> {            String msg = "当前会话在SSO-Server端尚未登录,请先访问"                    + "<a href='/sso/doLogin?name=sa&pwd=123456' target='_blank'> doLogin登录 </a>"                    + "进行登录之后,刷新页面开始授权";            return msg;        });        // 配置:登录处理函数         sso.setDoLoginHandle((name, pwd) -> {            // 此处仅做模拟登录,真实环境应该查询数据进行登录             if("sa".equals(name) && "123456".equals(pwd)) {                StpUtil.login(10001);                return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue());            }            return SaResult.error("登录失败!");        });        // 配置 Http 请求处理器 (在模式三的单点注销功能下用到,如不需要可以注释掉)         sso.setSendHttp(url -> {            try {                // 发起 http 请求                 System.out.println("------ 发起请求:" + url);                return Forest.get(url).executeAsString();            } catch (Exception e) {                e.printStackTrace();                return null;            }        });    }}

application.yml配置

# 端口server:    port: 9000# Sa-Token 配置sa-token:     # ------- SSO-模式一相关配置  (非模式一不需要配置)     # cookie:         # 配置 Cookie 作用域         # domain: stp.com     # ------- SSO-模式二相关配置     sso:         # Ticket有效期 (单位: 秒),默认五分钟         ticket-timeout: 300        # 所有允许的授权回调地址        allow-url: "*"        # 是否打开单点注销功能        is-slo: true        # ------- SSO-模式三相关配置 (下面的配置在SSO模式三并且 is-slo=true 时打开)        # 是否打开模式三         isHttp: true        # 接口调用秘钥(用于SSO模式三的单点注销功能)        secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor        # ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器(文档有步骤说明) spring:     # Redis配置 (SSO模式一和模式二使用Redis来同步会话)    redis:        # Redis数据库索引(默认为0)        database: 1        # Redis服务器地址        host: 127.0.0.1        # Redis服务器连接端口        port: 6379        # Redis服务器连接密码(默认为空)        password: forest:     # 关闭 forest 请求日志打印    log-enabled: false

访问统一授权地址:BFT28资讯网——每日最新资讯28at.com

  • http://localhost:9000/sso/auth

图片BFT28资讯网——每日最新资讯28at.com

可以看到这个页面目前非常简陋,这是因为我们以上的代码示例,主要目标是为了带大家从零搭建一个可用的SSO认证服务端,所以就对一些不太必要的步骤做了简化。BFT28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-35341-0.html再见,Shiro !你好,Sa-Token!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 再也不怕面试官问watch、computed、watchEffect的区别了

下一篇: 完美世界王雨蕴:文创思维让科技国潮产业绽放时代生命力

标签:
  • 热门焦点
  • Redmi Buds 4开箱简评:才199还有降噪 可以无脑入

    Redmi Buds 4开箱简评:才199还有降噪 可以无脑入

    在上个月举办的Redmi Note11T Pro系列新机发布会上,除了两款手机新品之外,Redmi还带来了两款TWS真无线蓝牙耳机产品,Redmi Buds 4和Redmi Buds 4 Pro,此前我们在Redmi Note11T
  • 十个简单但很有用的Python装饰器

    十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • 一个注解实现接口幂等,这样才优雅!

    一个注解实现接口幂等,这样才优雅!

    场景码猿慢病云管理系统中其实高并发的场景不是很多,没有必要每个接口都去考虑并发高的场景,比如添加住院患者的这个接口,具体的业务代码就不贴了,业务伪代码如下:图片上述代码有
  • “又被陈思诚骗了”

    “又被陈思诚骗了”

    作者|张思齐 出品|众面(ID:ZhongMian_ZM)如今的国产悬疑电影,成了陈思诚的天下。最近大爆电影《消失的她》票房突破30亿断层夺魁暑期档,陈思诚再度风头无两。你可以说陈思诚的
  • 年轻人的“职场羞耻感”,无处不在

    年轻人的“职场羞耻感”,无处不在

    作者:冯晓亭 陶 淘 李 欣 张 琳 马舒叶来源:燃次元&ldquo;人在职场,应该选择什么样的着装?&rdquo;近日,在网络上,一个与着装相关的帖子引发关注,在该帖子里,一位在高级写字楼亚洲金
  • 认真聊聊东方甄选:如何告别低垂的果实

    认真聊聊东方甄选:如何告别低垂的果实

    来源:山核桃作者:财经无忌爆火一年后,俞敏洪和他的东方甄选依旧是颇受外界关心的&ldquo;网红&rdquo;。7月5日至9日,为期5天的东方甄选&ldquo;甘肃行&rdquo;首次在自有App内直播,
  • iQOO Neo8 Pro评测:旗舰双芯加持 最强性能游戏旗舰

    iQOO Neo8 Pro评测:旗舰双芯加持 最强性能游戏旗舰

    【Techweb评测】去年10月,iQOO推出了一款Neo7手机,该机搭载了联发科天玑9000+,配备独显芯片Pro+,带来了同价位段最佳的游戏体验,一经上市便受到了诸多用
  • 三翼鸟智能家居亮相电博会,让用户体验更真实

    三翼鸟智能家居亮相电博会,让用户体验更真实

    2021电博会在青岛国际会展中心开幕中,三翼鸟直接把“家”搬到了现场,成为了展会的一大看点。这也是三翼鸟继9月9日发布了行业首个一站式定制智慧家平台后的
  • 荣耀Magic4 至臻版 首创智慧隐私通话 强劲影音系统

    荣耀Magic4 至臻版 首创智慧隐私通话 强劲影音系统

    2022年第一季度临近尾声,在该季度内,许多品牌陆续发布自己的最新产品,让大家从全新的角度来了解当今的手机技术。手机是电子设备中,更新迭代十分迅速的一款产品,基
Top