feat: api 参数签名模块允许多实例配置。 Closes #IAK2BI, #I9SPI1, #IAC0P9

This commit is contained in:
click33 2025-03-10 02:07:23 +08:00
parent aef5e04abe
commit 3d2cdbbb57
7 changed files with 116 additions and 4 deletions

View File

@ -32,6 +32,14 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface SaCheckSign {
/**
* 多实例下的 appid 用于区分不同的实例如不填写则代表使用全局默认实例 <br/>
* 允许以 #{} 的形式指定为请求参数#{appid}
*
* @return /
*/
String appid() default "";
/**
* 指定参与签名的参数有哪些如果不填写则默认为全部参数
*

View File

@ -17,7 +17,8 @@ package cn.dev33.satoken.annotation.handler;
import cn.dev33.satoken.annotation.SaCheckSign;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.sign.SaSignUtil;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.sign.SaSignMany;
import java.lang.reflect.Method;
@ -36,11 +37,17 @@ public class SaCheckSignHandler implements SaAnnotationHandlerInterface<SaCheckS
@Override
public void checkMethod(SaCheckSign at, Method method) {
_checkMethod(at.verifyParams());
_checkMethod(at.appid(), at.verifyParams());
}
public static void _checkMethod(String[] params) {
SaSignUtil.checkRequest(SaHolder.getRequest(), params);
public static void _checkMethod(String appid, String[] verifyParams) {
SaRequest req = SaHolder.getRequest();
// 如果 appid #{} 格式则从请求参数中获取
if(appid.startsWith("#{") && appid.endsWith("}")) {
String reqParamName = appid.substring(2, appid.length() - 1);
appid = req.getParam(reqParamName);
}
SaSignMany.getSignTemplate(appid).checkRequest(req, verifyParams);
}
}

View File

@ -18,6 +18,8 @@ package cn.dev33.satoken.config;
import cn.dev33.satoken.util.SaFoxUtil;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Sa-Token 配置类 Model
@ -186,6 +188,11 @@ public class SaTokenConfig implements Serializable {
*/
public SaSignConfig sign = new SaSignConfig();
/**
* API 签名配置 多实例
*/
public Map<String, SaSignConfig> signMany = new LinkedHashMap<>();
/**
* @return token 名称 同时也是 cookie 名称提交 token 时参数的名称存储 token 时的 key 前缀
@ -695,6 +702,25 @@ public class SaTokenConfig implements Serializable {
return this;
}
/**
* 获取 API 签名配置 多实例
*
* @return /
*/
public Map<String, SaSignConfig> getSignMany() {
return this.signMany;
}
/**
* 设置 API 签名配置 多实例
*
* @param signMany /
* @return /
*/
public SaTokenConfig setSignMany(Map<String, SaSignConfig> signMany) {
this.signMany = signMany;
return this;
}
@Override
public String toString() {
return "SaTokenConfig ["
@ -729,6 +755,7 @@ public class SaTokenConfig implements Serializable {
+ ", checkSameToken=" + checkSameToken
+ ", cookie=" + cookie
+ ", sign=" + sign
+ ", signMany=" + signMany
+ "]";
}

View File

@ -198,4 +198,7 @@ public interface SaErrorCode {
/** timestamp 超出允许的范围 */
int CODE_12203 = 12203;
/** 未找到对应 appid 的 SaSignConfig */
int CODE_12211 = 12211;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.sign;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaSignConfig;
import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.SaSignException;
import cn.dev33.satoken.fun.SaParamRetFunction;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* API 参数签名算法 - 多实例总控类
*
* @author click33
* @since 1.41.0
*/
public class SaSignMany {
/**
* 根据 appid 获取 SaSignConfig允许自定义
*/
public static SaParamRetFunction<String, SaSignConfig> findSaSignConfigMethod = (appid) -> {
return SaManager.getConfig().getSignMany().get(appid);
};
/**
* 获取 SaSignTemplate根据 appid
* @param appid /
* @return /
*/
public static SaSignTemplate getSignTemplate(String appid) {
// appid 为空返回全局默认 SaSignTemplate
if(SaFoxUtil.isEmpty(appid)){
return SaManager.getSaSignTemplate();
}
// 获取 SaSignConfig
SaSignConfig config = findSaSignConfigMethod.run(appid);
if(config == null){
throw new SaSignException("未找到签名配置appid=" + appid).setCode(SaErrorCode.CODE_12211);
}
// 创建 SaSignTemplate 并返回
return new SaSignTemplate(config);
}
}

View File

@ -1,6 +1,7 @@
package com.pj.test;
import cn.dev33.satoken.annotation.SaCheckHttpDigest;
import cn.dev33.satoken.annotation.SaCheckSign;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.spring.SpringMVCUtil;
import cn.dev33.satoken.stp.SaLoginParameter;
@ -40,6 +41,7 @@ public class TestController {
// 测试 浏览器访问 http://localhost:8081/test/test
@RequestMapping("test")
@SaCheckSign(appid = "#{appid}", verifyParams = {"name", "age"})
public SaResult test() {
System.out.println("------------进来了 " + SaFoxUtil.formatDate(new Date()));
// StpUtil.getLoginId();

View File

@ -21,6 +21,9 @@ sa-token:
sign:
# token签名密钥
secret-key: abc123
sign-many:
10001:
secret-key: 123456
spring:
# redis配置