Skip to content

Commit a54b006

Browse files
committed
还原简单的接口签名认证逻辑
1 parent 16da86b commit a54b006

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

src/main/java/com/company/project/framework/configurer/WebMvcConfigurerConfig.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
11
package com.company.project.framework.configurer;
22

33

4+
import org.apache.commons.lang3.StringUtils;
5+
import com.alibaba.fastjson.JSON;
46
import com.alibaba.fastjson.serializer.SerializerFeature;
57
import com.alibaba.fastjson.support.config.FastJsonConfig;
68
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
9+
import com.company.project.core.Result;
10+
import com.company.project.core.ResultCode;
11+
import org.apache.commons.codec.digest.DigestUtils;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
import org.springframework.beans.factory.annotation.Value;
715
import org.springframework.context.annotation.Configuration;
816
import org.springframework.http.MediaType;
917
import org.springframework.http.converter.HttpMessageConverter;
1018
import org.springframework.web.servlet.config.annotation.CorsRegistry;
19+
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
1120
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
1221
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
22+
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
23+
24+
import javax.servlet.http.HttpServletRequest;
25+
import javax.servlet.http.HttpServletResponse;
26+
import java.io.IOException;
1327
import java.nio.charset.StandardCharsets;
28+
import java.util.ArrayList;
1429
import java.util.Arrays;
30+
import java.util.Collections;
1531
import java.util.List;
1632

1733
/**
@@ -28,6 +44,9 @@
2844
@Configuration
2945
public class WebMvcConfigurerConfig implements WebMvcConfigurer {
3046

47+
private final Logger logger = LoggerFactory.getLogger(WebMvcConfigurer.class);
48+
@Value("${spring.profiles.active}")
49+
private String env;//当前激活的配置文件
3150
/**使用阿里 FastJson 作为JSON MessageConverter*/
3251
@Override
3352
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
@@ -47,7 +66,96 @@ public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
4766
public void addCorsMappings(CorsRegistry registry) {
4867
registry.addMapping("/**");
4968
}
69+
//添加拦截器
70+
71+
@Override
72+
public void addInterceptors(InterceptorRegistry registry) {
73+
//接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。
74+
if (!"dev".equals(env)) { //开发环境忽略签名认证
75+
registry.addInterceptor(new HandlerInterceptorAdapter() {
76+
@Override
77+
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
78+
//验证签名
79+
boolean pass = validateSign(request);
80+
if (pass) {
81+
return true;
82+
} else {
83+
logger.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}",
84+
request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
85+
86+
Result result = new Result();
87+
result.setCode(ResultCode.UNAUTHORIZED).setMessage("签名认证失败");
88+
responseResult(response, result);
89+
return false;
90+
}
91+
}
92+
});
93+
}
94+
}
95+
96+
private void responseResult(HttpServletResponse response, Result result) {
97+
response.setCharacterEncoding("UTF-8");
98+
response.setHeader("Content-type", "application/json;charset=UTF-8");
99+
response.setStatus(200);
100+
try {
101+
response.getWriter().write(JSON.toJSONString(result));
102+
} catch (IOException ex) {
103+
logger.error(ex.getMessage());
104+
}
105+
}
50106

107+
/**
108+
* 一个简单的签名认证,规则:
109+
* 1. 将请求参数按ascii码排序
110+
* 2. 拼接为a=value&b=value...这样的字符串(不包含sign)
111+
* 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较
112+
*/
113+
private boolean validateSign(HttpServletRequest request) {
114+
String requestSign = request.getParameter("sign");//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57
115+
if (StringUtils.isEmpty(requestSign)) {
116+
return false;
117+
}
118+
List<String> keys = new ArrayList<String>(request.getParameterMap().keySet());
119+
keys.remove("sign");//排除sign参数
120+
Collections.sort(keys);//排序
121+
122+
StringBuilder sb = new StringBuilder();
123+
for (String key : keys) {
124+
sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串
125+
}
126+
String linkString = sb.toString();
127+
linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最后一个'&'
128+
129+
String secret = "Potato";//密钥,自己修改
130+
String sign = DigestUtils.md5Hex(linkString + secret);//混合密钥md5
131+
132+
return StringUtils.equals(sign, requestSign);//比较
133+
}
134+
135+
private String getIpAddress(HttpServletRequest request) {
136+
String ip = request.getHeader("x-forwarded-for");
137+
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
138+
ip = request.getHeader("Proxy-Client-IP");
139+
}
140+
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
141+
ip = request.getHeader("WL-Proxy-Client-IP");
142+
}
143+
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
144+
ip = request.getHeader("HTTP_CLIENT_IP");
145+
}
146+
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
147+
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
148+
}
149+
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
150+
ip = request.getRemoteAddr();
151+
}
152+
// 如果是多级代理,那么取第一个ip为客户端ip
153+
if (ip != null && ip.indexOf(",") != -1) {
154+
ip = ip.substring(0, ip.indexOf(",")).trim();
155+
}
156+
157+
return ip;
158+
}
51159
@Override
52160
public void addResourceHandlers(ResourceHandlerRegistry registry) {
53161

0 commit comments

Comments
 (0)