2023-03-26 11:30:17 +08:00
|
|
|
|
# 前后端分离(无Cookie模式)
|
2020-02-06 00:52:49 +08:00
|
|
|
|
---
|
|
|
|
|
|
2022-07-04 11:48:29 +08:00
|
|
|
|
### 何为无 Cookie 模式?
|
2020-02-06 00:52:49 +08:00
|
|
|
|
|
2023-03-26 11:30:17 +08:00
|
|
|
|
无 Cookie 模式:特指不支持 Cookie 功能的终端,通俗来讲就是我们常说的 —— **前后端分离模式**。
|
2020-02-06 00:52:49 +08:00
|
|
|
|
|
2022-07-04 11:48:29 +08:00
|
|
|
|
常规 Web 端鉴权方法,一般由 `Cookie模式` 完成,而 Cookie 有两个特性:
|
|
|
|
|
1. 可由后端控制写入。
|
|
|
|
|
2. 每次请求自动提交。
|
2020-02-06 00:52:49 +08:00
|
|
|
|
|
2021-02-06 14:31:41 +08:00
|
|
|
|
这就使得我们在前端代码中,无需任何特殊操作,就能完成鉴权的全部流程(因为整个流程都是后端控制完成的)<br/>
|
2023-03-26 11:30:17 +08:00
|
|
|
|
而在app、小程序等前后端分离场景中,一般是没有 Cookie 这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊?
|
2021-02-06 14:31:41 +08:00
|
|
|
|
|
|
|
|
|
见招拆招,其实答案很简单:
|
2022-07-04 11:48:29 +08:00
|
|
|
|
- 不能后端控制写入了,就前端自己写入。(难点在**后端如何将 Token 传递到前端**)
|
|
|
|
|
- 每次请求不能自动提交了,那就手动提交。(难点在**前端如何将 Token 传递到后端**,同时**后端将其读取出来**)
|
2021-02-06 14:31:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1、后端将 token 返回到前端
|
2020-02-06 00:52:49 +08:00
|
|
|
|
|
2022-07-04 11:48:29 +08:00
|
|
|
|
1. 首先调用 `StpUtil.login(id)` 进行登录。
|
|
|
|
|
2. 调用 `StpUtil.getTokenInfo()` 返回当前会话的 token 详细参数。
|
|
|
|
|
- 此方法返回一个对象,其有两个关键属性:`tokenName`和`tokenValue`(token 的名称和 token 的值)。
|
|
|
|
|
- 将此对象传递到前台,让前端人员将这两个值保存到本地。
|
|
|
|
|
|
|
|
|
|
代码示例:
|
|
|
|
|
``` java
|
|
|
|
|
// 登录接口
|
|
|
|
|
@RequestMapping("doLogin")
|
|
|
|
|
public SaResult doLogin() {
|
|
|
|
|
// 第1步,先登录上
|
|
|
|
|
StpUtil.login(10001);
|
|
|
|
|
// 第2步,获取 Token 相关参数
|
|
|
|
|
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
|
|
|
|
// 第3步,返回给前端
|
|
|
|
|
return SaResult.data(tokenInfo);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2020-02-06 00:52:49 +08:00
|
|
|
|
|
2021-02-06 14:31:41 +08:00
|
|
|
|
### 2、前端将 token 提交到后端
|
2022-07-04 11:48:29 +08:00
|
|
|
|
1. 无论是app还是小程序,其传递方式都大同小异。
|
|
|
|
|
2. 那就是,将 token 塞到请求`header`里 ,格式为:`{tokenName: tokenValue}`。
|
2021-02-06 14:31:41 +08:00
|
|
|
|
3. 以经典跨端框架 [uni-app](https://uniapp.dcloud.io/) 为例:
|
2020-04-21 23:34:55 +08:00
|
|
|
|
|
|
|
|
|
**方式1,简单粗暴**
|
|
|
|
|
|
|
|
|
|
``` js
|
2021-02-12 01:57:31 +08:00
|
|
|
|
// 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);
|
|
|
|
|
}
|
|
|
|
|
});
|
2020-02-06 00:52:49 +08:00
|
|
|
|
```
|
2020-04-21 23:34:55 +08:00
|
|
|
|
|
|
|
|
|
**方式2,更加灵活**
|
|
|
|
|
|
|
|
|
|
``` js
|
2021-02-12 01:57:31 +08:00
|
|
|
|
// 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 = {
|
2021-07-22 20:36:46 +08:00
|
|
|
|
"content-type": "application/x-www-form-urlencoded"
|
2021-02-12 01:57:31 +08:00
|
|
|
|
};
|
|
|
|
|
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);
|
2020-02-06 00:52:49 +08:00
|
|
|
|
}
|
2021-02-12 01:57:31 +08:00
|
|
|
|
});
|
2020-02-06 00:52:49 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-07-04 11:48:29 +08:00
|
|
|
|
4. 只要按照如此方法将`token`值传递到后端,Sa-Token 就能像传统PC端一样自动读取到 token 值,进行鉴权。
|
|
|
|
|
5. 你可能会有疑问,难道我每个`ajax`都要写这么一坨?岂不是麻烦死了?
|
|
|
|
|
- 你当然不能每个 ajax 都写这么一坨,因为这种重复性代码都是要封装在一个函数里统一调用的。
|
2020-02-06 00:52:49 +08:00
|
|
|
|
|
|
|
|
|
|
2020-12-25 00:16:12 +08:00
|
|
|
|
### 其它解决方案?
|
2021-07-23 00:19:58 +08:00
|
|
|
|
如果你对 Cookie 非常了解,那你就会明白,所谓 Cookie ,本质上就是一个特殊的`header`参数而已,
|
2022-07-04 11:48:29 +08:00
|
|
|
|
而既然它只是一个 header 参数,我们就能手动模拟实现它,从而完成鉴权操作。
|
2021-02-06 14:31:41 +08:00
|
|
|
|
|
2022-07-04 11:48:29 +08:00
|
|
|
|
这其实是对`无Cookie模式`的另一种解决方案,有兴趣的同学可以百度了解一下,在此暂不赘述。
|
2020-02-06 00:52:49 +08:00
|
|
|
|
|
2022-10-17 01:16:10 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/up/NotCookieController.java"
|
|
|
|
|
target="_blank">
|
|
|
|
|
本章代码示例:Sa-Token 前后端分离样例 —— [ com.pj.cases.up.NotCookieController.java ]
|
|
|
|
|
</a>
|