mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-10-26 10:39:02 +08:00
新增不同 SSO Client 配置不同秘钥的方案
This commit is contained in:
@@ -37,6 +37,17 @@ public class SaSignConfig {
|
|||||||
private long timestampDisparity = 1000 * 60 * 15;
|
private long timestampDisparity = 1000 * 60 * 15;
|
||||||
|
|
||||||
|
|
||||||
|
public SaSignConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param secretKey 秘钥
|
||||||
|
*/
|
||||||
|
public SaSignConfig(String secretKey) {
|
||||||
|
this.secretKey = secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 API 调用签名秘钥
|
* 获取 API 调用签名秘钥
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import cn.dev33.satoken.util.SaFoxUtil;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import static cn.dev33.satoken.SaManager.log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 参数签名算法,在跨系统接口调用时防参数篡改、防重放攻击。
|
* API 参数签名算法,在跨系统接口调用时防参数篡改、防重放攻击。
|
||||||
*
|
*
|
||||||
@@ -42,6 +44,17 @@ import java.util.TreeMap;
|
|||||||
*/
|
*/
|
||||||
public class SaSignTemplate {
|
public class SaSignTemplate {
|
||||||
|
|
||||||
|
public SaSignTemplate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param signConfig 签名参数配置对象
|
||||||
|
*/
|
||||||
|
public SaSignTemplate(SaSignConfig signConfig) {
|
||||||
|
this.signConfig = signConfig;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------- 签名配置
|
// ----------- 签名配置
|
||||||
|
|
||||||
SaSignConfig signConfig;
|
SaSignConfig signConfig;
|
||||||
@@ -160,7 +173,14 @@ public class SaSignTemplate {
|
|||||||
// 计算签名
|
// 计算签名
|
||||||
String paramsStr = joinParamsDictSort(paramsMap);
|
String paramsStr = joinParamsDictSort(paramsMap);
|
||||||
String fullStr = paramsStr + "&" + key + "=" + secretKey;
|
String fullStr = paramsStr + "&" + key + "=" + secretKey;
|
||||||
return abstractStr(fullStr);
|
String signStr = abstractStr(fullStr);
|
||||||
|
|
||||||
|
// 输入日志,方便调试
|
||||||
|
log.debug("fullStr:{}", fullStr);
|
||||||
|
log.debug("signStr:{}", signStr);
|
||||||
|
|
||||||
|
// 返回
|
||||||
|
return signStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ server:
|
|||||||
port: 9000
|
port: 9000
|
||||||
|
|
||||||
# Sa-Token 配置
|
# Sa-Token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# ------- SSO-模式一相关配置 (非模式一不需要配置)
|
# ------- SSO-模式一相关配置 (非模式一不需要配置)
|
||||||
# cookie:
|
# cookie:
|
||||||
# 配置 Cookie 作用域
|
# 配置 Cookie 作用域
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ server:
|
|||||||
port: 9032
|
port: 9032
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# sso-client 相关配置
|
# sso-client 相关配置
|
||||||
sso-client:
|
sso-client:
|
||||||
# client 标识
|
# client 标识
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ server:
|
|||||||
port: 9003
|
port: 9003
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# sso-client 相关配置
|
# sso-client 相关配置
|
||||||
sso-client:
|
sso-client:
|
||||||
# client 标识
|
# client 标识
|
||||||
|
|||||||
@@ -41,12 +41,13 @@
|
|||||||
- [SSO模式一 共享Cookie同步会话](/sso/sso-type1)
|
- [SSO模式一 共享Cookie同步会话](/sso/sso-type1)
|
||||||
- [SSO模式二 URL重定向传播会话](/sso/sso-type2)
|
- [SSO模式二 URL重定向传播会话](/sso/sso-type2)
|
||||||
- [SSO模式三 Http请求获取会话](/sso/sso-type3)
|
- [SSO模式三 Http请求获取会话](/sso/sso-type3)
|
||||||
- [SSO整合:配置域名校验](/sso/sso-check-domain)
|
- [配置域名校验](/sso/sso-check-domain)
|
||||||
- [SSO整合:定制化登录页面](/sso/sso-custom-login)
|
- [定制化登录页面](/sso/sso-custom-login)
|
||||||
- [SSO整合:自定义API路由](/sso/sso-custom-api)
|
- [自定义API路由](/sso/sso-custom-api)
|
||||||
- [SSO扩展:前后端分离下的整合方案](/sso/sso-h5)
|
- [前后端分离下的整合方案](/sso/sso-h5)
|
||||||
- [SSO扩展:平台中心跳转模式](/sso/sso-home-jump)
|
- [平台中心跳转模式](/sso/sso-home-jump)
|
||||||
- [SSO扩展:常见问题总结](/sso/sso-questions)
|
- [不同 Client 不同秘钥](/sso/sso-diff-key)
|
||||||
|
- [常见问题总结](/sso/sso-questions)
|
||||||
- [Sa-Sso-Pro:单点登录商业版](/sso/sso-pro)
|
- [Sa-Sso-Pro:单点登录商业版](/sso/sso-pro)
|
||||||
|
|
||||||
- **OAuth2.0**
|
- **OAuth2.0**
|
||||||
|
|||||||
@@ -201,8 +201,10 @@ http://{host}:{port}/sso/logoutCall
|
|||||||
| loginId | 是 | 要注销的账号 id |
|
| loginId | 是 | 要注销的账号 id |
|
||||||
| timestamp | 是 | 当前时间戳,13位 |
|
| timestamp | 是 | 当前时间戳,13位 |
|
||||||
| nonce | 是 | 随机字符串 |
|
| nonce | 是 | 随机字符串 |
|
||||||
| client | 否 | 客户端标识,如果你在登录时向 sso-server 端传递了 client 值,那么在此处 sso-server 也会给你回传过来,否则此参数无值 |
|
| sign | 是 | 签名,生成算法:`md5( loginId={账号id}&nonce={随机字符串}×tamp={13位时间戳}&key={secretkey秘钥} )` |
|
||||||
| sign | 是 | 签名,生成算法:`md5( loginId={账号id}&nonce={随机字符串}×tamp={13位时间戳}&key={secretkey秘钥} )` 如果 client 参数有值,则client也要参与签名,放在 loginId 参数签名(字典顺序)|
|
| client | 否 | 客户端标识,如果你在登录时向 sso-server 端传递了 client 值,那么在此处 sso-server 也会给你回传过来,否则此参数无值。如果此参数有值,则此参数也要参与签名,放在 loginId 参数前面(字典顺序) |
|
||||||
|
| autoLogout | 否 | 是否为“登录client超过最大数量”引起的自动注销(true=超限系统自动注销,false=用户主动发起注销)。如果此参数有值,则此参数也要参与签名,放在 client 参数前面(字典顺序) |
|
||||||
|
|
||||||
|
|
||||||
返回数据:
|
返回数据:
|
||||||
|
|
||||||
|
|||||||
119
sa-token-doc/sso/sso-diff-key.md
Normal file
119
sa-token-doc/sso/sso-diff-key.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# 不同 SSO Client 配置不同秘钥
|
||||||
|
|
||||||
|
在校验 ticket、单点注销等操作发起的 http 调用时,需要配置秘钥参数,像这样:
|
||||||
|
|
||||||
|
<!---------------------------- tabs:start ---------------------------->
|
||||||
|
<!------------- tab:yaml 风格 ------------->
|
||||||
|
``` yaml
|
||||||
|
sa-token:
|
||||||
|
sign:
|
||||||
|
# API 接口调用秘钥
|
||||||
|
secret-key: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
|
||||||
|
```
|
||||||
|
<!------------- tab:properties 风格 ------------->
|
||||||
|
``` properties
|
||||||
|
# 接口调用秘钥
|
||||||
|
sa-token.sign.secret-key=kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
|
||||||
|
```
|
||||||
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
|
||||||
|
|
||||||
|
如果 SSO Client 端和 SSO Server 端配置的秘钥不同,则无法调通请求,显示无效签名:
|
||||||
|
``` js
|
||||||
|
{
|
||||||
|
"code": 500,
|
||||||
|
"msg": "无效签名:9f1b453817bfeac56d2f772a66c01eb2",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你有多个 SSO Client,你可能想让每个应用配置不同的秘钥,让它们彼此之间不能互相“冒充”,怎么做呢?
|
||||||
|
|
||||||
|
### 1、首先在 SSO Client 端,你需要配置上不同的 Client 标识参数:
|
||||||
|
|
||||||
|
例如在 client1 我们配置上:
|
||||||
|
|
||||||
|
<!---------------------------- tabs:start ---------------------------->
|
||||||
|
<!------------- tab:yaml 风格 ------------->
|
||||||
|
``` yaml
|
||||||
|
sa-token:
|
||||||
|
sso-client:
|
||||||
|
# 当前 client 标识
|
||||||
|
client: sso-client1
|
||||||
|
# ...
|
||||||
|
sign:
|
||||||
|
# sso-client1 使用的秘钥
|
||||||
|
secret-key: secret-key-xxxx-1
|
||||||
|
```
|
||||||
|
<!------------- tab:properties 风格 ------------->
|
||||||
|
``` properties
|
||||||
|
# 当前 client 标识
|
||||||
|
sa-token.sso-client.client=sso-client1
|
||||||
|
|
||||||
|
# sso-client1 使用的秘钥
|
||||||
|
sa-token.sign.secret-key=secret-key-xxxx-1
|
||||||
|
```
|
||||||
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
|
||||||
|
|
||||||
|
在 client2 我们配置上:
|
||||||
|
|
||||||
|
<!---------------------------- tabs:start ---------------------------->
|
||||||
|
<!------------- tab:yaml 风格 ------------->
|
||||||
|
``` yaml
|
||||||
|
sa-token:
|
||||||
|
sso-client:
|
||||||
|
# 当前 client 标识
|
||||||
|
client: sso-client2
|
||||||
|
# ...
|
||||||
|
sign:
|
||||||
|
# sso-client2 使用的秘钥
|
||||||
|
secret-key: secret-key-xxxx-2
|
||||||
|
```
|
||||||
|
<!------------- tab:properties 风格 ------------->
|
||||||
|
``` properties
|
||||||
|
# 当前 client 标识
|
||||||
|
sa-token.sso-client.client=sso-client2
|
||||||
|
|
||||||
|
# sso-client2 使用的秘钥
|
||||||
|
sa-token.sign.secret-key=secret-key-xxxx-2
|
||||||
|
```
|
||||||
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
|
||||||
|
|
||||||
|
### 2、然后在 SSO Server 端,重写获取秘钥的函数
|
||||||
|
|
||||||
|
在 SSO Server 端新建 `CustomSaSsoServerTemplate.java`,继承 `SaSsoServerTemplate`,重写其 `getSignTemplate` 函数:
|
||||||
|
|
||||||
|
``` java
|
||||||
|
/**
|
||||||
|
* 自定义 SaSsoServerTemplate 子类
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CustomSaSsoServerTemplate extends SaSsoServerTemplate {
|
||||||
|
|
||||||
|
// 存储所有 client 的秘钥
|
||||||
|
static Map<String, SaSignTemplate> signMap = new HashMap<>();
|
||||||
|
static {
|
||||||
|
signMap.put("sso-client1", new SaSignTemplate(new SaSignConfig("secret-key-xxxx-1")));
|
||||||
|
signMap.put("sso-client2", new SaSignTemplate(new SaSignConfig("secret-key-xxxx-2")));
|
||||||
|
signMap.put("sso-client3", new SaSignTemplate(new SaSignConfig("secret-key-xxxx-3")));
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SaSignTemplate getSignTemplate(String client) {
|
||||||
|
// 先从自定义的 signMap 中获取
|
||||||
|
SaSignTemplate saSignTemplate = signMap.get(client);
|
||||||
|
if (saSignTemplate != null) {
|
||||||
|
return saSignTemplate;
|
||||||
|
}
|
||||||
|
// 找不到就返回全局默认的 SaSignTemplate
|
||||||
|
return SaManager.getSaSignTemplate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
至此完成,其它代码一切照旧。
|
||||||
|
|
||||||
|
|
||||||
@@ -363,6 +363,9 @@ forest:
|
|||||||
``` properties
|
``` properties
|
||||||
# 接口调用秘钥
|
# 接口调用秘钥
|
||||||
sa-token.sign.secret-key=kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
|
sa-token.sign.secret-key=kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
|
||||||
|
|
||||||
|
# 关闭 forest 请求日志打印
|
||||||
|
forest.log-enabled=false
|
||||||
```
|
```
|
||||||
<!---------------------------- tabs:end ---------------------------->
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public class SaSsoClientProcessor {
|
|||||||
|
|
||||||
// 无论登录时选择的是模式二还是模式三
|
// 无论登录时选择的是模式二还是模式三
|
||||||
// 在注销时都应该按照模式三的方法,通过 http 请求调用 sso-server 的单点注销接口来做到全端下线
|
// 在注销时都应该按照模式三的方法,通过 http 请求调用 sso-server 的单点注销接口来做到全端下线
|
||||||
if(cfg.getIsSlo() && ! cfg.getIsHttp()) {
|
if(cfg.getIsSlo()) {
|
||||||
return ssoLogoutByMode3();
|
return ssoLogoutByMode3();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user