refactor(signature): 重构了获取 appSecret 的方式,引入了 ApiSignatureSecretFetcher 接口,允许不同的服务实现获取 appSecret 的逻辑
parent
fd34572c48
commit
4702d8ed74
|
@ -2,8 +2,11 @@ package cn.iocoder.yudao.framework.signature.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||||
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.fetcher.ApiSignatureSecretFetcher;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.fetcher.DefaultApiSignatureSecretFetcherImpl;
|
||||||
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
@ -16,8 +19,9 @@ import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
public class YudaoApiSignatureAutoConfiguration {
|
public class YudaoApiSignatureAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ApiSignatureAspect signatureAspect(ApiSignatureRedisDAO signatureRedisDAO) {
|
public ApiSignatureAspect signatureAspect(ApiSignatureRedisDAO signatureRedisDAO,
|
||||||
return new ApiSignatureAspect(signatureRedisDAO);
|
ApiSignatureSecretFetcher apiSignatureSecretFetcher) {
|
||||||
|
return new ApiSignatureAspect(signatureRedisDAO, apiSignatureSecretFetcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -25,4 +29,9 @@ public class YudaoApiSignatureAutoConfiguration {
|
||||||
return new ApiSignatureRedisDAO(stringRedisTemplate);
|
return new ApiSignatureRedisDAO(stringRedisTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ApiSignatureSecretFetcher apiSignatureSecretFetcher(ApiSignatureRedisDAO apiSignatureRedisDAO) {
|
||||||
|
return new DefaultApiSignatureSecretFetcherImpl(apiSignatureRedisDAO);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.fetcher.ApiSignatureSecretFetcher;
|
||||||
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
@ -36,6 +37,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
|
||||||
public class ApiSignatureAspect {
|
public class ApiSignatureAspect {
|
||||||
|
|
||||||
private final ApiSignatureRedisDAO signatureRedisDAO;
|
private final ApiSignatureRedisDAO signatureRedisDAO;
|
||||||
|
private final ApiSignatureSecretFetcher apiSignatureSecretFetcher;
|
||||||
|
|
||||||
@Before("@annotation(signature)")
|
@Before("@annotation(signature)")
|
||||||
public void beforePointCut(JoinPoint joinPoint, ApiSignature signature) {
|
public void beforePointCut(JoinPoint joinPoint, ApiSignature signature) {
|
||||||
|
@ -58,7 +60,7 @@ public class ApiSignatureAspect {
|
||||||
}
|
}
|
||||||
// 1.2 校验 appId 是否能获取到对应的 appSecret
|
// 1.2 校验 appId 是否能获取到对应的 appSecret
|
||||||
String appId = request.getHeader(signature.appId());
|
String appId = request.getHeader(signature.appId());
|
||||||
String appSecret = signatureRedisDAO.getAppSecret(appId);
|
String appSecret = apiSignatureSecretFetcher.getAppSecret(appId);
|
||||||
Assert.notNull(appSecret, "[appId({})] 找不到对应的 appSecret", appId);
|
Assert.notNull(appSecret, "[appId({})] 找不到对应的 appSecret", appId);
|
||||||
|
|
||||||
// 2. 校验签名【重要!】
|
// 2. 校验签名【重要!】
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.iocoder.yudao.framework.signature.core.fetcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Secret 提取器 <br/>
|
||||||
|
* 允许不同的服务获取 appSecret
|
||||||
|
*
|
||||||
|
* @author diaohang
|
||||||
|
*/
|
||||||
|
public interface ApiSignatureSecretFetcher {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 appSecret
|
||||||
|
*
|
||||||
|
* @param appId appId
|
||||||
|
* @return 可以为空,表示找不到对应的 appSecret
|
||||||
|
*/
|
||||||
|
String getAppSecret(String appId);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.iocoder.yudao.framework.signature.core.fetcher;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author diaohang
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DefaultApiSignatureSecretFetcherImpl implements ApiSignatureSecretFetcher {
|
||||||
|
|
||||||
|
private final ApiSignatureRedisDAO apiSignatureRedisDAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAppSecret(String appId) {
|
||||||
|
return apiSignatureRedisDAO.getAppSecret(appId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.crypto.digest.DigestUtil;
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||||
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.fetcher.ApiSignatureSecretFetcher;
|
||||||
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -20,7 +21,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ApiSignatureTest} 的单元测试
|
* {@link ApiSignatureTest} 的单元测试
|
||||||
|
@ -31,6 +33,9 @@ public class ApiSignatureTest {
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private ApiSignatureAspect apiSignatureAspect;
|
private ApiSignatureAspect apiSignatureAspect;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ApiSignatureSecretFetcher apiSignatureSecretFetcher;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ApiSignatureRedisDAO signatureRedisDAO;
|
private ApiSignatureRedisDAO signatureRedisDAO;
|
||||||
|
|
||||||
|
@ -57,12 +62,12 @@ public class ApiSignatureTest {
|
||||||
when(request.getHeader(eq("timestamp"))).thenReturn(String.valueOf(timestamp));
|
when(request.getHeader(eq("timestamp"))).thenReturn(String.valueOf(timestamp));
|
||||||
when(request.getHeader(eq("nonce"))).thenReturn(nonce);
|
when(request.getHeader(eq("nonce"))).thenReturn(nonce);
|
||||||
when(request.getHeader(eq("sign"))).thenReturn(sign);
|
when(request.getHeader(eq("sign"))).thenReturn(sign);
|
||||||
when(request.getParameterMap()).thenReturn(MapUtil.<String, String[]>builder()
|
when(request.getParameterMap()).thenReturn(
|
||||||
.put("v1", new String[]{"k1"}).put("k1", new String[]{"v1"}).build());
|
MapUtil.<String, String[]>builder().put("v1", new String[] {"k1"}).put("k1", new String[] {"v1"}).build());
|
||||||
when(request.getContentType()).thenReturn("application/json");
|
when(request.getContentType()).thenReturn("application/json");
|
||||||
when(request.getReader()).thenReturn(new BufferedReader(new StringReader("test")));
|
when(request.getReader()).thenReturn(new BufferedReader(new StringReader("test")));
|
||||||
// mock 方法
|
// mock 方法
|
||||||
when(signatureRedisDAO.getAppSecret(eq(appId))).thenReturn(appSecret);
|
when(apiSignatureSecretFetcher.getAppSecret(eq(appId))).thenReturn(appSecret);
|
||||||
when(signatureRedisDAO.setNonce(eq(appId), eq(nonce), eq(120), eq(TimeUnit.SECONDS))).thenReturn(true);
|
when(signatureRedisDAO.setNonce(eq(appId), eq(nonce), eq(120), eq(TimeUnit.SECONDS))).thenReturn(true);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
|
|
Loading…
Reference in New Issue