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 class SaApiKeyTemplate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*默认命名空间
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_NAMESPACE = "apikey";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命名空间
|
||||||
|
*/
|
||||||
|
public String namespace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raw Session 读写委托
|
* Raw Session 读写委托
|
||||||
*/
|
*/
|
||||||
public SaRawSessionDelegator rawSessionDelegator = new SaRawSessionDelegator("apikey");
|
public SaRawSessionDelegator rawSessionDelegator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 raw-session 中的保存索引列表使用的 key
|
* 在 raw-session 中的保存索引列表使用的 key
|
||||||
*/
|
*/
|
||||||
public static final String API_KEY_LIST = "__HD_API_KEY_LIST";
|
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
|
// ------------------- ApiKey
|
||||||
|
|
||||||
@ -73,7 +94,7 @@ public class SaApiKeyTemplate {
|
|||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
public ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
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());
|
SaSession session = rawSessionDelegator.getSessionById(ak.getLoginId());
|
||||||
ArrayList<String> apiKeyList = session.get(API_KEY_LIST, ArrayList::new);
|
ArrayList<String> apiKeyList = session.get(API_KEY_LIST, ArrayList::new);
|
||||||
@ -170,7 +191,7 @@ public class SaApiKeyTemplate {
|
|||||||
getSaTokenDao().deleteObject(splicingApiKeySaveKey(apiKey));
|
getSaTokenDao().deleteObject(splicingApiKeySaveKey(apiKey));
|
||||||
|
|
||||||
// 删索引
|
// 删索引
|
||||||
if(SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
if(getIsRecordIndex()) {
|
||||||
// RawSession 中不存在,提前退出
|
// RawSession 中不存在,提前退出
|
||||||
SaSession session = rawSessionDelegator.getSessionById(ak.getLoginId(), false);
|
SaSession session = rawSessionDelegator.getSessionById(ak.getLoginId(), false);
|
||||||
if(session == null) {
|
if(session == null) {
|
||||||
@ -199,7 +220,7 @@ public class SaApiKeyTemplate {
|
|||||||
*/
|
*/
|
||||||
public void deleteApiKeyByLoginId(Object loginId) {
|
public void deleteApiKeyByLoginId(Object loginId) {
|
||||||
// 先判断是否开启索引
|
// 先判断是否开启索引
|
||||||
if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
if(! getIsRecordIndex()) {
|
||||||
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 deleteApiKeyByLoginId 操作");
|
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 deleteApiKeyByLoginId 操作");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -375,7 +396,7 @@ public class SaApiKeyTemplate {
|
|||||||
*/
|
*/
|
||||||
public void adjustIndex(Object loginId, SaSession session) {
|
public void adjustIndex(Object loginId, SaSession session) {
|
||||||
// 先判断是否开启索引
|
// 先判断是否开启索引
|
||||||
if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
if(! getIsRecordIndex()) {
|
||||||
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 adjustIndex 操作");
|
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 adjustIndex 操作");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -431,7 +452,7 @@ public class SaApiKeyTemplate {
|
|||||||
*/
|
*/
|
||||||
public List<ApiKeyModel> getApiKeyList(Object loginId) {
|
public List<ApiKeyModel> getApiKeyList(Object loginId) {
|
||||||
// 先判断是否开启索引
|
// 先判断是否开启索引
|
||||||
if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
if(! getIsRecordIndex()) {
|
||||||
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 getApiKeyList 操作");
|
SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行 getApiKeyList 操作");
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
@ -464,13 +485,13 @@ public class SaApiKeyTemplate {
|
|||||||
public String readApiKeyValue(SaRequest request) {
|
public String readApiKeyValue(SaRequest request) {
|
||||||
|
|
||||||
// 优先从请求参数中获取
|
// 优先从请求参数中获取
|
||||||
String apiKey = request.getParam(API_KEY_PARAMETER_NAME);
|
String apiKey = request.getParam(namespace);
|
||||||
if(SaFoxUtil.isNotEmpty(apiKey)) {
|
if(SaFoxUtil.isNotEmpty(apiKey)) {
|
||||||
return apiKey;
|
return apiKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 然后请求头
|
// 然后请求头
|
||||||
apiKey = request.getHeader(API_KEY_PARAMETER_NAME);
|
apiKey = request.getHeader(namespace);
|
||||||
if(SaFoxUtil.isNotEmpty(apiKey)) {
|
if(SaFoxUtil.isNotEmpty(apiKey)) {
|
||||||
return apiKey;
|
return apiKey;
|
||||||
}
|
}
|
||||||
@ -496,7 +517,6 @@ public class SaApiKeyTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 拼接key
|
// ------------------- 拼接key
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -505,7 +525,7 @@ public class SaApiKeyTemplate {
|
|||||||
* @return key
|
* @return key
|
||||||
*/
|
*/
|
||||||
public String splicingApiKeySaveKey(String apiKey) {
|
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() {
|
public boolean getIsRecordIndex() {
|
||||||
// if(! SaManager.getSaApiKeyDataLoader().getIsRecordIndex()) {
|
return SaManager.getSaApiKeyDataLoader().getIsRecordIndex();
|
||||||
// SaManager.getLog().warn("当前 API Key 模块未开启索引记录功能,无法执行此操作");
|
}
|
||||||
// throw new ApiKeyException("当前 API Key 模块未开启索引记录功能,无法执行此操作").setCode(SaErrorCode.CODE_12305);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,11 @@ public interface SaApiKeyDataLoader {
|
|||||||
/**
|
/**
|
||||||
* 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
* 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
||||||
*
|
*
|
||||||
|
* @param namespace /
|
||||||
* @param apiKey /
|
* @param apiKey /
|
||||||
* @return ApiKeyModel
|
* @return ApiKeyModel
|
||||||
*/
|
*/
|
||||||
default ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
default ApiKeyModel getApiKeyModelFromDatabase(String namespace, String apiKey) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class SaApiKeyDataLoaderImpl implements SaApiKeyDataLoader {
|
|||||||
|
|
||||||
// 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
// 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
||||||
@Override
|
@Override
|
||||||
public ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
public ApiKeyModel getApiKeyModelFromDatabase(String namespace, String apiKey) {
|
||||||
return apiKeyMockMapper.getApiKeyModel(apiKey);
|
return apiKeyMockMapper.getApiKeyModel(apiKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.pj.mock;
|
package com.pj.mock;
|
||||||
|
|
||||||
import cn.dev33.satoken.apikey.model.ApiKeyModel;
|
import cn.dev33.satoken.apikey.model.ApiKeyModel;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -12,7 +12,7 @@ import java.util.Map;
|
|||||||
* @author click33
|
* @author click33
|
||||||
* @since 2025/4/4
|
* @since 2025/4/4
|
||||||
*/
|
*/
|
||||||
@Service
|
@Component
|
||||||
public class SaApiKeyMockMapper {
|
public class SaApiKeyMockMapper {
|
||||||
|
|
||||||
// 添加模拟测试数据
|
// 添加模拟测试数据
|
||||||
|
@ -11,5 +11,5 @@ public class SaTokenJwtDemoApplication {
|
|||||||
SpringApplication.run(SaTokenJwtDemoApplication.class, args);
|
SpringApplication.run(SaTokenJwtDemoApplication.class, args);
|
||||||
System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
|
System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -223,7 +223,7 @@ public class SaApiKeyDataLoaderImpl implements SaApiKeyDataLoader {
|
|||||||
|
|
||||||
// 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
// 根据 apiKey 从数据库获取 ApiKeyModel 信息 (实现此方法无需为数据做缓存处理,框架内部已包含缓存逻辑)
|
||||||
@Override
|
@Override
|
||||||
public ApiKeyModel getApiKeyModelFromDatabase(String apiKey) {
|
public ApiKeyModel getApiKeyModelFromDatabase(String namespace, String apiKey) {
|
||||||
return apiKeyMapper.getApiKeyModel(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