mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-06-28 13:34:18 +08:00
feat: API Key 模块新增 namespace 命名空间,为多账号模式提供支持
This commit is contained in:
parent
49ec4d9690
commit
fab7f200cc
@ -41,20 +41,41 @@ import java.util.List;
|
||||
*/
|
||||
public class SaApiKeyTemplate {
|
||||
|
||||
/**
|
||||
*默认命名空间
|
||||
*/
|
||||
public static final String DEFAULT_NAMESPACE = "apikey";
|
||||
|
||||
/**
|
||||
* 命名空间
|
||||
*/
|
||||
public String namespace;
|
||||
|
||||
/**
|
||||
* Raw Session 读写委托
|
||||
*/
|
||||
public SaRawSessionDelegator rawSessionDelegator = new SaRawSessionDelegator("apikey");
|
||||
public SaRawSessionDelegator rawSessionDelegator;
|
||||
|
||||
/**
|
||||
* 在 raw-session 中的保存索引列表使用的 key
|
||||
*/
|
||||
public static final String API_KEY_LIST = "__HD_API_KEY_LIST";
|
||||
|
||||
public SaApiKeyTemplate(){
|
||||
this(DEFAULT_NAMESPACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络传输时的参数名称 (字母全小写)
|
||||
* 实例化
|
||||
* @param namespace 命名空间,用于多实例隔离
|
||||
*/
|
||||
public static final String API_KEY_PARAMETER_NAME = "apikey";
|
||||
public SaApiKeyTemplate(String namespace){
|
||||
if(SaFoxUtil.isEmpty(namespace)) {
|
||||
throw new ApiKeyException("namespace 不能为空");
|
||||
}
|
||||
this.namespace = namespace;
|
||||
this.rawSessionDelegator = new SaRawSessionDelegator(namespace);
|
||||
}
|
||||
|
||||
// ------------------- ApiKey
|
||||
|
||||
@ -73,7 +94,7 @@ public class SaApiKeyTemplate {
|
||||
* @return /
|
||||
*/
|
||||
public ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
||||
return SaManager.getSaApiKeyDataLoader().getApiKeyModelFromDatabase(apiKey);
|
||||
return SaManager.getSaApiKeyDataLoader().getApiKeyModelFromDatabase(namespace, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,7 +154,7 @@ public class SaApiKeyTemplate {
|
||||
}
|
||||
|
||||
// 记录索引
|
||||
if (SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
||||
if (getIsRecordIndex()) {
|
||||
// 添加索引
|
||||
SaSession session = rawSessionDelegator.getSessionById(ak.getLoginId());
|
||||
ArrayList<String> apiKeyList = session.get(API_KEY_LIST, ArrayList::new);
|
||||
@ -170,7 +191,7 @@ public class SaApiKeyTemplate {
|
||||
getSaTokenDao().deleteObject(splicingApiKeySaveKey(apiKey));
|
||||
|
||||
// 删索引
|
||||
if(SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
||||
if(getIsRecordIndex()) {
|
||||
// RawSession 中不存在,提前退出
|
||||
SaSession session = rawSessionDelegator.getSessionById(ak.getLoginId(), false);
|
||||
if(session == null) {
|
||||
@ -199,7 +220,7 @@ public class SaApiKeyTemplate {
|
||||
*/
|
||||
public void deleteApiKeyByLoginId(Object loginId) {
|
||||
// 先判断是否开启索引
|
||||
if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
||||
if(! getIsRecordIndex()) {
|
||||
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 deleteApiKeyByLoginId 操作");
|
||||
return;
|
||||
}
|
||||
@ -375,7 +396,7 @@ public class SaApiKeyTemplate {
|
||||
*/
|
||||
public void adjustIndex(Object loginId, SaSession session) {
|
||||
// 先判断是否开启索引
|
||||
if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
||||
if(! getIsRecordIndex()) {
|
||||
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 adjustIndex 操作");
|
||||
return;
|
||||
}
|
||||
@ -431,7 +452,7 @@ public class SaApiKeyTemplate {
|
||||
*/
|
||||
public List<ApiKeyModel> getApiKeyList(Object loginId) {
|
||||
// 先判断是否开启索引
|
||||
if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
||||
if(! getIsRecordIndex()) {
|
||||
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 getApiKeyList 操作");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
@ -464,13 +485,13 @@ public class SaApiKeyTemplate {
|
||||
public String readApiKeyValue(SaRequest request) {
|
||||
|
||||
// 优先从请求参数中获取
|
||||
String apiKey = request.getParam(API_KEY_PARAMETER_NAME);
|
||||
String apiKey = request.getParam(namespace);
|
||||
if(SaFoxUtil.isNotEmpty(apiKey)) {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
// 然后请求头
|
||||
apiKey = request.getHeader(API_KEY_PARAMETER_NAME);
|
||||
apiKey = request.getHeader(namespace);
|
||||
if(SaFoxUtil.isNotEmpty(apiKey)) {
|
||||
return apiKey;
|
||||
}
|
||||
@ -496,7 +517,6 @@ public class SaApiKeyTemplate {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------- 拼接key
|
||||
|
||||
/**
|
||||
@ -505,7 +525,7 @@ public class SaApiKeyTemplate {
|
||||
* @return key
|
||||
*/
|
||||
public String splicingApiKeySaveKey(String apiKey) {
|
||||
return getSaTokenConfig().getTokenName() + ":apikey:" + apiKey;
|
||||
return getSaTokenConfig().getTokenName() + ":" + namespace + ":" + apiKey;
|
||||
}
|
||||
|
||||
|
||||
@ -530,13 +550,10 @@ public class SaApiKeyTemplate {
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验是否开启了索引记录功能,如果未开启则抛出异常
|
||||
* 是否保存索引信息
|
||||
*/
|
||||
// protected void checkOpenRecordIndex() {
|
||||
// if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
||||
// SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行此操作");
|
||||
// throw new ApiKeyException("当前 API Key 模块未开启索引记录功能,无法执行此操作").setCode(SaErrorCode.CODE_12305);
|
||||
// }
|
||||
// }
|
||||
public boolean getIsRecordIndex() {
|
||||
return SaManager.getSaApiKeyDataLoader().getIsRecordIndex();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,10 +38,11 @@ public interface SaApiKeyDataLoader {
|
||||
/**
|
||||
* 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
||||
*
|
||||
* @param namespace /
|
||||
* @param apiKey /
|
||||
* @return ApiKeyModel
|
||||
*/
|
||||
default ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
||||
default ApiKeyModel getApiKeyModelFromDatabase(String namespace, String apiKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ public class SaApiKeyDataLoaderImpl implements SaApiKeyDataLoader {
|
||||
|
||||
// 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
||||
@Override
|
||||
public ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
||||
public ApiKeyModel getApiKeyModelFromDatabase(String namespace, String apiKey) {
|
||||
return apiKeyMockMapper.getApiKeyModel(apiKey);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.pj.mock;
|
||||
|
||||
import cn.dev33.satoken.apikey.model.ApiKeyModel;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -12,7 +12,7 @@ import java.util.Map;
|
||||
* @author click33
|
||||
* @since 2025/4/4
|
||||
*/
|
||||
@Service
|
||||
@Component
|
||||
public class SaApiKeyMockMapper {
|
||||
|
||||
// 添加模拟测试数据
|
||||
|
@ -11,5 +11,5 @@ public class SaTokenJwtDemoApplication {
|
||||
SpringApplication.run(SaTokenJwtDemoApplication.class, args);
|
||||
System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -223,7 +223,7 @@ public class SaApiKeyDataLoaderImpl implements SaApiKeyDataLoader {
|
||||
|
||||
// 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
||||
@Override
|
||||
public ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
||||
public ApiKeyModel getApiKeyModelFromDatabase(String namespace, String apiKey) {
|
||||
return apiKeyMapper.getApiKeyModel(apiKey);
|
||||
}
|
||||
|
||||
@ -240,7 +240,28 @@ public class SaApiKeyDataLoaderImpl implements SaApiKeyDataLoader {
|
||||
|
||||
|
||||
|
||||
|
||||
### 6、多账号模式使用
|
||||
|
||||
如果系统有多套账号表,比如 Admin 和 User,只需要指定不同的命名空间即可:
|
||||
|
||||
例如 User 账号的 API Key,我们使用原生 `SaApiKeyUtil` 进行创建与校验。
|
||||
|
||||
对于 Admin 账号的 API Key,我们则新建一个 `SaApiKeyTemplate` 实例
|
||||
|
||||
``` java
|
||||
// 新建 Admin 账号的 apiKeyTemplate 对象,命名空间为 "admin-apikey"
|
||||
public static SaApiKeyTemplate adminApiKeyTemplate = new SaApiKeyTemplate("admin-apikey");
|
||||
|
||||
// 创建一个新的 ApiKey,并返回
|
||||
@RequestMapping("/createApiKey")
|
||||
public SaResult createApiKey() {
|
||||
ApiKeyModel akModel = adminApiKeyTemplate.createApiKeyModel(StpUtil.getLoginId()).setTitle("test");
|
||||
adminApiKeyTemplate.saveApiKey(akModel);
|
||||
return SaResult.data(akModel);
|
||||
}
|
||||
|
||||
// ...校验、查询等操作,均使用新创建的 adminApiKeyTemplate,而非原生 `SaApiKeyUtil`
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user