添加签名计算

pull/236/head
13066656961 2024-07-24 23:22:35 +08:00
parent e7f7b1b3ac
commit ce6b0634f5
3 changed files with 126 additions and 5 deletions

View File

@ -0,0 +1,113 @@
package vip.xiaonuo.common.filter;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.HandlerInterceptor;
import vip.xiaonuo.common.exception.CommonException;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
/**
*
*/
public class SignatureInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
/*从header中读取appSign*/
String sign = httpServletRequest.getHeader("appSign");
if (StringUtils.isEmpty(sign)) {
throw new CommonException("没有签名信息!", 40052050);
}
String appTime = httpServletRequest.getParameter("appTime");
if (StringUtils.isEmpty(appTime)) {
throw new CommonException("请在Parameter中传入时间戳毫秒级!", 40052051);
}
Map<String, String[]> bodyData = SignatureInterceptor.sortMapByKey(httpServletRequest.getParameterMap());
if (bodyData == null) {
throw new CommonException("没有请求参数!", 40052052);
}
String original = SignatureInterceptor.transformationUri(bodyData);
if (StringUtils.isEmpty(sign) || !this.isMatching(sign, original)) {
throw new CommonException("应用签名验证不通过!", 40024053);
}
return true;
}
public static String makeSign(String appId, String appKey, String body) {
String sha1 = DigestUtils.sha1Hex(appKey + body + appKey);
return DigestUtils.md5Hex(sha1 + appId);
}
public static Map<String, String[]> sortMapByKey(Map<String, String[]> map) {
if (map == null || map.isEmpty()) {
return null;
}
Map<String, String[]> sortMap = new TreeMap<>(Comparator.naturalOrder());
sortMap.putAll(map);
return sortMap;
}
public void parseBodySign(String sign, Map<String, String[]> body) throws CommonException {
}
public Boolean isMatching(String sign, String original) {
Environment environment = SpringUtil.getBean(Environment.class);
String securityAccessKey = environment.getProperty("spring.enjoy-buy.security-access-key");
String securityAccessSecret = environment.getProperty("spring.enjoy-buy.security-access-secret");
String upSign = this.makeSign(securityAccessKey, securityAccessSecret, original);
return sign.equalsIgnoreCase(upSign);
}
public static String transformationUri(Map<String, String[]> map) {
StringBuilder stringBuilder = new StringBuilder();
for (String key : map.keySet()) {
Object value = map.get(key);
if ("appSign".equalsIgnoreCase(key) || value == null || StringUtils.isEmpty(value.toString())) {
continue;
}
stringBuilder.append(key);
stringBuilder.append("=");
if (map.get(key).getClass().isArray()) {
Object[] objects = (Object[]) map.get(key);
StringBuilder valueBuilder = new StringBuilder();
for (Object o : objects) {
valueBuilder.append(o);
valueBuilder.append(",");
}
valueBuilder.deleteCharAt(valueBuilder.length() - 1);
stringBuilder.append(valueBuilder);
} else {
stringBuilder.append(map.get(key));
}
stringBuilder.append("&");
}
if (stringBuilder.length() > 0) {
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
return stringBuilder.toString();
}
}

View File

@ -28,6 +28,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import vip.xiaonuo.auth.core.enums.SaClientTypeEnum;
import vip.xiaonuo.auth.core.util.StpClientLoginUserUtil;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.common.filter.SignatureInterceptor;
import java.util.List;
@ -56,6 +57,10 @@ public class AuthConfigure implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
// 注册注解拦截器,并排除不需要注解鉴权的接口地址 (与登录拦截器无关,只是说明哪些接口不需要被拦截器拦截,此处都拦截)
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new SignatureInterceptor())
.addPathPatterns("/**")
/*排除文档相关地址*/
.excludePathPatterns("/doc**", "/webjars/**", "/v3/api-docs/**");
}
@Primary

View File

@ -27,9 +27,9 @@ spring.servlet.multipart.max-file-size=100MB
# mysql
spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/snowy?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&useInformationSchema=true
spring.datasource.dynamic.datasource.master.username=root
spring.datasource.dynamic.datasource.master.password=123456
spring.datasource.dynamic.datasource.master.url=jdbc:mysql://10.10.10.7:3306/membershipsystem?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&useInformationSchema=true
spring.datasource.dynamic.datasource.master.username=MembershipSystem
spring.datasource.dynamic.datasource.master.password=ZtCMBHbjwanJWxbm
spring.datasource.dynamic.strict=true
# postgres
@ -100,9 +100,9 @@ spring.jackson.serialization.write-dates-as-timestamps=true
# redis configuration
#########################################
spring.data.redis.database=1
spring.data.redis.host=127.0.0.1
spring.data.redis.host=10.10.10.3
spring.data.redis.port=6379
spring.data.redis.password=
spring.data.redis.password=121121Jie
spring.data.redis.timeout=10s
spring.data.redis.lettuce.pool.max-active=200
@ -201,3 +201,6 @@ springdoc.group-configs[6].packages-to-scan=vip.xiaonuo.sys
# common configuration
snowy.config.common.front-url=http://localhost:81
snowy.config.common.backend-url=http://localhost:82
spring.enjoy-buy.security-access-key=wxd504412d92c5ffe7
spring.enjoy-buy.security-access-secret=0c7bf34850bb54158d261e5914e807ee