feat: sso 模块新增配置文件方式启用“不同 client 不同秘钥”能力

This commit is contained in:
click33 2025-04-25 21:40:05 +08:00
parent 476910dffb
commit 84506d49f0
9 changed files with 187 additions and 18 deletions

View File

@ -74,6 +74,19 @@ public class SaSignConfig {
}
}
/**
* 复制对象
* @return /
*/
public SaSignConfig copy() {
SaSignConfig obj = new SaSignConfig();
obj.secretKey = this.secretKey;
obj.timestampDisparity = this.timestampDisparity;
obj.digestAlgo = this.digestAlgo;
obj.digestMethod = this.digestMethod;
return obj;
}
// -------------- 策略函数

View File

@ -4,6 +4,9 @@ server:
# Sa-Token 配置
sa-token:
# 打印操作日志
is-log: true
# ------- SSO-模式一相关配置 (非模式一不需要配置)
# cookie:
# 配置 Cookie 作用域
@ -15,22 +18,27 @@ sa-token:
ticket-timeout: 300
# 所有允许的授权回调地址
allow-url: "*"
# API 接口调用秘钥 (默认)
secret-key: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
# 是否启用匿名 client
allow-anon-client: false
# ------- SSO-模式三相关配置 下面的配置在使用SSO模式三时打开
# 是否打开模式三
is-http: true
allow-anon-client: false
clients:
# 应用 sso-client2采用模式二对接 (跨域、同Redis)
sso-client2:
client: sso-client2
allow-url: http://sa-sso-client1.com:9002/sso/login
allow-url: "*"
# 应用 sso-client3采用模式三对接 (跨域、跨Redis)
sso-client3:
client: sso-client3
secret-key: SSO-C3-kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
allow-url: "*"
sign:
# API 接口调用秘钥
secret-key: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
# ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器文档有步骤说明
spring:

View File

@ -15,7 +15,7 @@ sa-token:
sign:
# API 接口调用秘钥
secret-key: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
secret-key: SSO-C2-kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
# 配置Sa-Token单独使用的Redis连接 此处需要和SSO-Server端连接同一个Redis
alone-redis:

View File

@ -4,16 +4,19 @@ server:
# sa-token配置
sa-token:
# 打印操作日志
is-log: true
# sso-client 相关配置
sso-client:
# 应用标识
client: sso-client3
# sso-server 端主机地址
server-url: http://sa-sso-server.com:9000
# 使用 Http 请求校验ticket (模式三)
is-http: true
sign:
# API 接口调用秘钥
secret-key: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
secret-key: SSO-C3-kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
spring:
# 配置 Redis 连接 此处与SSO-Server端连接不同的Redis

View File

@ -89,6 +89,11 @@ public class SaSsoClientConfig implements Serializable {
*/
public Boolean isHttp = false;
/**
* API 调用签名秘钥
*/
public String secretKey;
/**
* 是否校验参数签名方便本地调试用的一个配置项生产环境请务必为true
*/
@ -274,6 +279,26 @@ public class SaSsoClientConfig implements Serializable {
return this;
}
/**
* 获取 API 调用签名秘钥
*
* @return /
*/
public String getSecretKey() {
return this.secretKey;
}
/**
* 设置 API 调用签名秘钥
*
* @param secretKey /
* @return 对象自身
*/
public SaSsoClientConfig setSecretKey(String secretKey) {
this.secretKey = secretKey;
return this;
}
/**
* 获取 是否校验参数签名方便本地调试用的一个配置项生产环境请务必为true
*
@ -307,6 +332,7 @@ public class SaSsoClientConfig implements Serializable {
+ ", currSsoLogoutCall=" + currSsoLogoutCall
+ ", isSlo=" + isSlo
+ ", isHttp=" + isHttp
+ ", secretKey=" + secretKey
+ ", isCheckSign=" + isCheckSign
+ "]";
}

View File

@ -47,7 +47,10 @@ public class SaSsoClientModel implements Serializable {
*/
public Boolean isSlo = true;
/**
* API 调用签名秘钥
*/
public String secretKey;
// 额外方法
@ -61,7 +64,6 @@ public class SaSsoClientModel implements Serializable {
return this;
}
// get set
/**
@ -116,12 +118,33 @@ public class SaSsoClientModel implements Serializable {
return this;
}
/**
* 获取 API 调用签名秘钥
*
* @return /
*/
public String getSecretKey() {
return this.secretKey;
}
/**
* 设置 API 调用签名秘钥
*
* @param secretKey /
* @return 对象自身
*/
public SaSsoClientModel setSecretKey(String secretKey) {
this.secretKey = secretKey;
return this;
}
@Override
public String toString() {
return "SaSsoClientModel ["
+ "client=" + client
+ ", allowUrl=" + allowUrl
+ ", isSlo=" + isSlo
+ ", secretKey=" + secretKey
+ "]";
}

View File

@ -94,6 +94,11 @@ public class SaSsoServerConfig implements Serializable {
*/
public Boolean isCheckSign = true;
/**
* API 调用签名秘钥
*/
public String secretKey;
/**
* Client 信息配置列表
*/
@ -298,6 +303,26 @@ public class SaSsoServerConfig implements Serializable {
return this;
}
/**
* 获取 API 调用签名秘钥
*
* @return /
*/
public String getSecretKey() {
return this.secretKey;
}
/**
* 设置 API 调用签名秘钥
*
* @param secretKey /
* @return 对象自身
*/
public SaSsoServerConfig setSecretKey(String secretKey) {
this.secretKey = secretKey;
return this;
}
/**
* 获取 Client 信息配置列表
*
@ -331,6 +356,7 @@ public class SaSsoServerConfig implements Serializable {
+ ", maxRegClient=" + maxRegClient
+ ", isCheckSign=" + isCheckSign
+ ", allowAnonClient=" + allowAnonClient
+ ", secretKey=" + secretKey
+ ", clients=" + clients
+ "]";
}

View File

@ -16,6 +16,8 @@
package cn.dev33.satoken.sso.template;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaSignConfig;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.sso.SaSsoManager;
import cn.dev33.satoken.sso.config.SaSsoClientConfig;
import cn.dev33.satoken.sso.error.SaSsoErrorCode;
@ -191,6 +193,25 @@ public class SaSsoClientTemplate extends SaSsoTemplate {
return SaFoxUtil.joinParam(url, signParamsStr);
}
/**
* 获取底层使用的 API 签名对象
* @param client 指定客户端标识 null 代表获取默认的
* @return /
*/
@Override
public SaSignTemplate getSignTemplate(String client) {
SaSignConfig signConfig = SaManager.getSaSignTemplate().getSignConfigOrGlobal().copy();
// 使用 secretKey 的优先级SSO 模块全局配置 > sign 模块默认配置
String secretKey = getClientConfig().getSecretKey();
if(SaFoxUtil.isEmpty(secretKey)) {
secretKey = signConfig.getSecretKey();
}
signConfig.setSecretKey(secretKey);
return new SaSignTemplate(signConfig);
}
// ------------------- 发起请求 -------------------

View File

@ -16,7 +16,10 @@
package cn.dev33.satoken.sso.template;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaSignConfig;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.sso.SaSsoManager;
import cn.dev33.satoken.sso.config.SaSsoClientModel;
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
@ -260,12 +263,8 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
*/
public SaSsoClientModel getClientNotNull(String client) {
if(SaFoxUtil.isEmpty(client)) {
SaSsoServerConfig serverConfig = getServerConfig();
if(serverConfig.getAllowAnonClient()) {
SaSsoClientModel scm = new SaSsoClientModel();
scm.setAllowUrl(serverConfig.getAllowUrl());
scm.setIsSlo(serverConfig.getIsSlo());
return scm;
if(getServerConfig().getAllowAnonClient()) {
return getAnonClient();
} else {
throw new SaSsoException("client 标识不可为空");
}
@ -278,6 +277,23 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
}
}
/**
* 获取匿名 client 信息
*
* @return /
*/
public SaSsoClientModel getAnonClient() {
SaSsoServerConfig serverConfig = getServerConfig();
SaSsoClientModel scm = new SaSsoClientModel();
scm.setAllowUrl(serverConfig.getAllowUrl());
scm.setIsSlo(serverConfig.getIsSlo());
scm.setSecretKey(serverConfig.getSecretKey());
if(SaFoxUtil.isEmpty(scm.getSecretKey())) {
scm.setSecretKey(SaManager.getSaSignTemplate().getSignConfigOrGlobal().getSecretKey());
}
return scm;
}
/**
* 获取应用信息无效 client 返回 null
*
@ -558,6 +574,39 @@ public class SaSsoServerTemplate extends SaSsoTemplate {
// ---------------------- 重构 ----------------------
/**
* 校验 Ticket 获取账号id如果此ticket是有效的则立即删除
* @param ticket Ticket码
* @param client client 标识
*/
public void checkTicketVerifySign(SaRequest req, String ticket, String client) {
SaSignTemplate signTemplate = getSignTemplate(client);
signTemplate.checkRequest(req, paramName.client, paramName.ticket, paramName.ssoLogoutCall);
}
/**
* 获取底层使用的 API 签名对象
* @param client 指定客户端标识 null 代表获取默认的
* @return /
*/
@Override
public SaSignTemplate getSignTemplate(String client) {
SaSignConfig signConfig = SaManager.getSaSignTemplate().getSignConfigOrGlobal().copy();
SaSsoClientModel clientModel = getClientNotNull(client);
// 使用 secretKey 的优先级client 单独配置 > SSO 模块全局配置 > sign 模块默认配置
String secretKey = clientModel.getSecretKey();
if (SaFoxUtil.isEmpty(secretKey) && SaFoxUtil.isNotEmpty(client)) {
secretKey = getServerConfig().getSecretKey();
}
if(SaFoxUtil.isEmpty(secretKey)) {
secretKey = signConfig.getSecretKey();
}
signConfig.setSecretKey(secretKey);
return new SaSignTemplate(signConfig);
}