mirror of https://gitee.com/xiaonuobase/snowy
添加签名计算
parent
e7f7b1b3ac
commit
ce6b0634f5
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue