目前绝大多数系统都已经采用 “前后端分离” 架构来设计了,传统的Session模式鉴权也不再适合这种架构(或者需要额外写很多的代码来专门适配)。
Sa-Token 是一个 java 轻量级权限认证框架,专为前后端分离架构打造,主要解决登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相关问题。
Gitee 开源地址:https://gitee.com/dromara/sa-token
(相关资料图)
本文将介绍在 Springboot 架构下的前后端分离项目,如何使用 Sa-Token 方便的完成登录认证。
首先在项目中引入 Sa-Token 依赖:
cn.dev33 sa-token-spring-boot-starter 1.34.0
注:如果你使用的是 SpringBoot 3.x
,只需要将 sa-token-spring-boot-starter
修改为 sa-token-spring-boot3-starter
即可。
无 Cookie 模式:特指不支持 Cookie 功能的终端,通俗来讲就是我们常说的 —— 前后端分离模式。
常规 Web 端鉴权方法,一般由 Cookie模式
完成,而 Cookie 有两个特性:
这就使得我们在前端代码中,无需任何特殊操作,就能完成鉴权的全部流程(因为整个流程都是后端控制完成的)而在app、小程序等前后端分离场景中,一般是没有 Cookie 这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊?
见招拆招,其实答案很简单:
不能后端控制写入了,就前端自己写入。(难点在后端如何将 Token 传递到前端)每次请求不能自动提交了,那就手动提交。(难点在前端如何将 Token 传递到后端,同时后端将其读取出来)三、后端将 token 返回到前端首先调用StpUtil.login(id)
进行登录。调用 StpUtil.getTokenInfo()
返回当前会话的 token 详细参数。此方法返回一个对象,其有两个关键属性:tokenName
和tokenValue
(token 的名称和 token 的值)。将此对象传递到前台,让前端人员将这两个值保存到本地。代码示例:
// 登录接口@RequestMapping("doLogin")public SaResult doLogin() {// 第1步,先登录上 StpUtil.login(10001);// 第2步,获取 Token 相关参数 SaTokenInfo tokenInfo = StpUtil.getTokenInfo();// 第3步,返回给前端 return SaResult.data(tokenInfo);}
四、前端将 token 提交到后端无论是app还是小程序,其传递方式都大同小异。那就是,将 token 塞到请求header
里 ,格式为:{tokenName: tokenValue}
。以经典跨端框架 uni-app 为例:方式1,简单粗暴
// 1、首先在登录时,将 tokenValue 存储在本地,例如:uni.setStorageSync("tokenValue", tokenValue);// 2、在发起ajax请求的地方,获取这个值,并塞到header里 uni.request({url: "https://www.example.com/request", // 仅为示例,并非真实接口地址。header: {"content-type": "application/x-www-form-urlencoded","satoken": uni.getStorageSync("tokenValue")// 关键代码, 注意参数名字是 satoken },success: (res) => {console.log(res.data);}});
方式2,更加灵活
// 1、首先在登录时,将tokenName和tokenValue一起存储在本地,例如:uni.setStorageSync("tokenName", tokenName); uni.setStorageSync("tokenValue", tokenValue); // 2、在发起ajax的地方,获取这两个值, 并组织到head里 var tokenName = uni.getStorageSync("tokenName");// 从本地缓存读取tokenName值var tokenValue = uni.getStorageSync("tokenValue");// 从本地缓存读取tokenValue值var header = {"content-type": "application/x-www-form-urlencoded"};if (tokenName != undefined && tokenName != "") {header[tokenName] = tokenValue;}// 3、后续在发起请求时将 header 对象塞到请求头部 uni.request({url: "https://www.example.com/request", // 仅为示例,并非真实接口地址。header: header,success: (res) => {console.log(res.data);}});
只要按照如此方法将token
值传递到后端,Sa-Token 就能像传统PC端一样自动读取到 token 值,进行鉴权。你可能会有疑问,难道我每个ajax
都要写这么一坨?岂不是麻烦死了?你当然不能每个 ajax 都写这么一坨,因为这种重复性代码都是要封装在一个函数里统一调用的。其它解决方案:
如果你对 Cookie 非常了解,那你就会明白,所谓 Cookie ,本质上就是一个特殊的header
参数而已,而既然它只是一个 header 参数,我们就能手动模拟实现它,从而完成鉴权操作。
这其实是对无Cookie模式
的另一种解决方案,有兴趣的同学可以百度了解一下,在此暂不赘述。
为了更加直观的显示出 前后端一体架构 和 前后端分离架构 的差异,此处再提供一个示例:
package com.pj.cases.up;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import cn.dev33.satoken.stp.SaTokenInfo;import cn.dev33.satoken.stp.StpUtil;import cn.dev33.satoken.util.SaResult;/** * Sa-Token 前后端分离模式示例 * * @author kong * @since 2022-10-17 */@RestController@RequestMapping("/NotCookie/")public class NotCookieController {// 前后端一体模式的登录样例 ---- http://localhost:8081/NotCookie/doLogin?name=zhang&pwd=123456@RequestMapping("doLogin")public SaResult doLogin(String name, String pwd) {if("zhang".equals(name) && "123456".equals(pwd)) {// 会话登录 StpUtil.login(10001); return SaResult.ok();}return SaResult.error("登录失败");}// 前后端分离模式的登录样例 ---- http://localhost:8081/NotCookie/doLogin2?name=zhang&pwd=123456@RequestMapping("doLogin2")public SaResult doLogin2(String name, String pwd) {if("zhang".equals(name) && "123456".equals(pwd)) {// 会话登录 StpUtil.login(10001);// 与常规登录不同点之处:这里需要把 Token 信息从响应体中返回到前端 SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); return SaResult.data(tokenInfo);}return SaResult.error("登录失败");}}
接口一:Token 将在 Cookie 上下文返回到前端,并由浏览器每次请求时自动提交,这种模式适合前后端一体的架构。接口二:Token 将在响应 body 里返回到前端,并由前端手动存储,并手动在每次请求时提交,这种模式适合前后端分离的架构。六、自定义 Token 提交的前缀在某些系统中,前端提交token时会在前面加个固定的前缀,例如:
{"satoken": "Bearer xxxx-xxxx-xxxx-xxxx"}
此时后端如果不做任何特殊处理,框架将会把Bearer
视为token的一部分,无法正常读取token信息,导致鉴权失败。
为此,我们需要在yml中添加如下配置:
sa-token: # token前缀token-prefix: Bearer
此时 Sa-Token 便可在读取 Token 时裁剪掉 Bearer
,成功获取xxxx-xxxx-xxxx-xxxx
。
注意点:
Token前缀 与 Token值 之间必须有一个空格。一旦配置了 Token前缀,则前端提交Token
时,必须带有前缀,否则会导致框架无法读取 Token。由于Cookie
中无法存储空格字符,也就意味配置 Token 前缀后,Cookie 鉴权方式将会失效,此时只能将 Token 提交到header
里进行传输。七、自定义 Token 风格Sa-Token默认的token生成策略是uuid风格,其模样类似于:623368f0-ae5e-4475-a53f-93e4225f16ae
。如果你对这种风格不太感冒,还可以将token生成设置为其他风格。
怎么设置呢?只需要在yml配置文件里设置 sa-token.token-style=风格类型
即可,其有多种取值:
// 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生成风格。
怎么做呢?只需要重写 SaStrategy
策略类的 createToken
算法即可:
1、在SaTokenConfigure
配置类中添加代码:
@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样式:
gfuPSwZsnUhwgz08GTCH4wOgasWtc3odP4HLwXJ7NDGOximTvT4OlW19zeLH
参考资料Sa-Token 文档:https://sa-token.ccGitee 仓库地址:https://gitee.com/dromara/sa-tokenGitHub 仓库地址:https://github.com/dromara/sa-token
上一篇:50.1万!报名总人数公布
下一篇:最后一页
一、架构分析目前绝大多数系统都已经采用“前后端分离”架构来设计
央视网介绍,欧阳夏丹籍贯为广西桂林,中央电视台新闻频道主持人,2003
基础化工行业债券&定增&新股双周报:金浦钛业拟定向增发募资9 00亿元
这一天,家住碧桂园凤锦庭院的张芸正常下班,走到小区门口,看到了八里
2023年高考将于6月7日、8日、9日举行。今年,湖北省高考报名总人数为50
大象新闻
格隆汇6月5日丨腾亚精工301125SZ公布关于首次公开发行前已发行股份上市
2023年6月4日,第四届5G千兆网产业论坛在北京国家会议中心成功举办。论
其中上海方面产品数量环比递增10%,各地分社暑期产品数量环比增加30%
大象新闻
人民网
澎湃新闻
6月5日,浙江湖州德清县,一男子在厕所内持刀将一女子杀伤,后女子经抢
近日,国网乌鲁木齐供电公司促请乌鲁木齐市发改委共同发布《乌鲁木齐市
最近有小伙伴在对王者荣耀进行修改名称的时候发现改名功能出现异常导致
北京论道时间:2023年6月15—16日地点:北京朝阳悠唐皇冠假日酒店六层
6月3日,“V快乐满电启辰”东风日产启辰大VDD-i超混动(图片)正式开启预
6月2日,广东深圳。哥哥在房间外听到妹妹的哭声,跑着来到妹妹身边,轻
截至6月5日17时,河南已收获小麦5278 6万亩(约占全省种植面积的61 9%)
大象新闻记者李莉芸视频报道6月5日, 亲戚小孩毁了我的动漫周边 词条冲
X 关闭
X 关闭
06-05 20:07:25
06-05 18:32:56
06-05 17:54:42
06-05 17:11:28
06-05 16:56:26