OAuth2模块与会话登录模块 数据互通

This commit is contained in:
click33
2022-02-06 18:06:55 +08:00
parent 91d90dd901
commit 116f7d0976
9 changed files with 253 additions and 25 deletions

View File

@@ -0,0 +1,72 @@
package cn.dev33.satoken.stp;
import java.util.Map;
/**
*
* 快速构建 调用 `StpUtil.login()` 时的 [配置参数 Model ]
*
* @author kong
*
*/
public class SaLoginConfig {
/**
* @param device 此次登录的客户端设备标识
* @return SaLoginModel配置对象
*/
public static SaLoginModel setDevice(String device) {
return create().setDevice(device);
}
/**
* @param isLastingCookie 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
* @return 对象自身
*/
public static SaLoginModel setIsLastingCookie(Boolean isLastingCookie) {
return create().setIsLastingCookie(isLastingCookie);
}
/**
* @param timeout 指定此次登录token的有效期, 单位:秒 如未指定自动取全局配置的timeout值
* @return 对象自身
*/
public static SaLoginModel setTimeout(Long timeout) {
return create().setTimeout(timeout);
}
/**
* @param extraData 扩展信息只在jwt模式下生效
* @return 对象自身
*/
public static SaLoginModel setExtraData(Map<String, Object> extraData) {
return create().setExtraData(extraData);
}
/**
* @param token 预定Token预定本次登录生成的Token值
* @return 对象自身
*/
public static SaLoginModel setToken(String token) {
return create().setToken(token);
}
/**
* 写入扩展数据只在jwt模式下生效
* @param key 键
* @param value 值
* @return 对象自身
*/
public static SaLoginModel setExtra(String key, Object value) {
return create().setExtra(key, value);
}
/**
* 静态方法获取一个 SaLoginModel 对象
* @return SaLoginModel 对象
*/
public static SaLoginModel create() {
return new SaLoginModel();
}
}

View File

@@ -35,16 +35,21 @@ public class SaLoginModel {
*/
public Map<String, Object> extraData;
/**
* 预定Token预定本次登录生成的Token值
*/
public String token;
/**
* @return 参考 {@link #device}
* @return 此次登录的客户端设备标识
*/
public String getDevice() {
return device;
}
/**
* @param device 参考 {@link #device}
* @param device 此次登录的客户端设备标识
* @return 对象自身
*/
public SaLoginModel setDevice(String device) {
@@ -53,14 +58,14 @@ public class SaLoginModel {
}
/**
* @return 参考 {@link #isLastingCookie}
* @return 参考 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
*/
public Boolean getIsLastingCookie() {
return isLastingCookie;
}
/**
* @param isLastingCookie 参考 {@link #isLastingCookie}
* @param isLastingCookie 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
* @return 对象自身
*/
public SaLoginModel setIsLastingCookie(Boolean isLastingCookie) {
@@ -69,14 +74,14 @@ public class SaLoginModel {
}
/**
* @return 参考 {@link #timeout}
* @return 指定此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的timeout值)
*/
public Long getTimeout() {
return timeout;
}
/**
* @param timeout 参考 {@link #timeout}
* @param timeout 指定此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的timeout值)
* @return 对象自身
*/
public SaLoginModel setTimeout(long timeout) {
@@ -85,14 +90,14 @@ public class SaLoginModel {
}
/**
* @return 参考 {@link #extraData}
* @return 扩展信息只在jwt模式下生效
*/
public Map<String, Object> getExtraData() {
return extraData;
}
/**
* @param extraData 参考 {@link #extraData}
* @param extraData 扩展信息只在jwt模式下生效
* @return 对象自身
*/
public SaLoginModel setExtraData(Map<String, Object> extraData) {
@@ -100,11 +105,39 @@ public class SaLoginModel {
return this;
}
/**
* @return 预定Token预定本次登录生成的Token值
*/
public String getToken() {
return token;
}
/**
* @param token 预定Token预定本次登录生成的Token值
* @return 对象自身
*/
public SaLoginModel setToken(String token) {
this.token = token;
return this;
}
/*
* toString
*/
@Override
public String toString() {
return "SaLoginModel [device=" + device + ", isLastingCookie=" + isLastingCookie + ", timeout=" + timeout
+ ", extraData=" + extraData + ", token=" + token + "]";
}
// ------ 附加方法
/**
* 写入扩展数据只在jwt模式下生效
* @param key 键
* @param value 值
* @return
* @return 对象自身
*/
public SaLoginModel setExtra(String key, Object value) {
if(this.extraData == null) {
@@ -183,14 +216,6 @@ public class SaLoginModel {
return new SaLoginModel();
}
/**
* toString
*/
@Override
public String toString() {
return "SaLoginModel [device=" + device + ", isLastingCookie=" + isLastingCookie + ", timeout=" + timeout + "]";
}
/**
* 更换为 getDeviceOrDefault()

View File

@@ -274,6 +274,29 @@ public class StpLogic {
* @param loginModel 此次登录的参数Model
*/
public void login(Object id, SaLoginModel loginModel) {
// 1、创建会话
String token = createLoginSession(id, loginModel);
// 2、在当前客户端注入Token
setTokenValue(token, loginModel.getCookieTimeout());
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @return 返回会话令牌
*/
public String createLoginSession(Object id) {
return createLoginSession(id, new SaLoginModel());
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @param loginModel 此次登录的参数Model
* @return 返回会话令牌
*/
public String createLoginSession(Object id, SaLoginModel loginModel) {
SaTokenException.throwByNull(id, "账号id不能为空");
@@ -300,7 +323,11 @@ public class StpLogic {
}
// 如果至此仍未成功创建tokenValue, 则开始生成一个
if(tokenValue == null) {
if(SaFoxUtil.isEmpty(loginModel.getToken())) {
tokenValue = createTokenValue(id, loginModel.getDeviceOrDefault(), loginModel.getTimeout(), loginModel.getExtraData());
} else {
tokenValue = loginModel.getToken();
}
}
// ------ 3. 获取 User-Session , 续期
@@ -314,14 +341,14 @@ public class StpLogic {
// token -> id 映射关系
saveTokenToIdMapping(tokenValue, id, loginModel.getTimeout());
// 在当前会话写入tokenValue
setTokenValue(tokenValue, loginModel.getCookieTimeout());
// 写入 [token-last-activity]
setLastActivityToNow(tokenValue);
// $$ 通知监听器账号xxx 登录成功
SaManager.getSaTokenListener().doLogin(loginType, id, loginModel);
// 返回Token
return tokenValue;
}
// --- 注销

View File

@@ -132,6 +132,25 @@ public class StpUtil {
stpLogic.login(id, loginModel);
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @return 返回会话令牌
*/
public static String createLoginSession(Object id) {
return stpLogic.createLoginSession(id);
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @param loginModel 此次登录的参数Model
* @return 返回会话令牌
*/
public static String createLoginSession(Object id, SaLoginModel loginModel) {
return stpLogic.createLoginSession(id, loginModel);
}
// --- 注销
/**

View File

@@ -136,6 +136,25 @@ public class StpUserUtil {
stpLogic.login(id, loginModel);
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @return 返回会话令牌
*/
public static String createLoginSession(Object id) {
return stpLogic.createLoginSession(id);
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @param loginModel 此次登录的参数Model
* @return 返回会话令牌
*/
public static String createLoginSession(Object id, SaLoginModel loginModel) {
return stpLogic.createLoginSession(id, loginModel);
}
// --- 注销
/**

View File

@@ -235,7 +235,6 @@ public class TestController {
return AjaxJson.getSuccessData("登录成功");
}
// 测试 浏览器访问: http://localhost:8081/test/test
@RequestMapping("test")
public AjaxJson test() {

View File

@@ -50,6 +50,7 @@
- [OAuth2-Server搭建](/oauth2/oauth2-server)
- [OAuth2-Server端-API列表](/oauth2/oauth2-api)
- [OAuth2-二次开发说明](/oauth2/oauth2-dev)
- [OAuth2-与登录会话实现数据互通](/oauth2/oauth2-interworking)
- **微服务**
- [分布式Session会话](/micro/dcs-session)

View File

@@ -0,0 +1,65 @@
# Sa-Token-OAuth2 与登录会话实现数据互通
---
### 前提
前提,我们:
- 把 OAuth2 模块生成的令牌称作资源令牌access_token
- 把 StpUtil 登录会话生成的令牌称作会话令牌satoken
正常情况下,资源令牌 与 会话令牌 的数据是不互通的,具体表现就是:当我们拿着 access_token 去访问 satoken 令牌的接口,会被抛出异常:`无效Tokenxxxxx`
那么,有什么办法可以做到这两个模块的数据互通呢?
### OAuth2-Server 端数据互通
很简单,你只需要在 `SaOAuth2TemplateImpl` 实现类中继续重写 Access-Token 的生成策略:
``` java
@Component
public class SaOAuth2TemplateImpl extends SaOAuth2Template {
// ... 其它代码
// 重写 Access-Token 生成策略复用登录会话的Token
@Override
public String randomAccessToken(String clientId, Object loginId, String scope) {
String tokenValue = StpUtil.createLoginSession(loginId);
return tokenValue;
}
}
```
重启项目,然后在 OAuth2 模块授权登录,现在生成的 `access_token` ,可以用来访问 `satoken` 的会话接口了。
### OAuth2-Client 数据互通
除了Server端Client端也可以打通 `access_token` 与 `satoken` 会话。做法是在 Client 端拿到 `access_token` 后进行登录时,使用 SaLoginModel 预定登录生成的 Token 值
``` java
// 1. 获取到access_token
String access_token = ...
// 2. 登录时预定生成的token
StpUtil.login(uid, SaLoginConfig.setToken(access_token));
// 3. 其它代码...
```
### 注意点
数据互通,让前端与后端的交互更加方便,一个 token 即可访问所有接口但也一定程度上失去了OAuth2的 “不同 Client 不同权限” 的设计意义,
同时也默认每个 Client 都拥有了账号的会话权限access_token 与 satoken 为同一个)。
应该根据自己的架构合理分析是否应该整合数据互通。

View File

@@ -72,6 +72,7 @@ StpUtil.login(10001, new SaLoginModel()
.setDevice("PC") // 此次登录的客户端设备标识, 用于[同端互斥登录]时指定此次登录的设备名称
.setIsLastingCookie(true) // 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
.setTimeout(60 * 60 * 24 * 7) // 指定此次登录token的有效期, 单位:秒 如未指定自动取全局配置的timeout值
.setToken("xxxx-xxxx-xxxx-xxxx") // 预定此次登录的生成的Token
);
```