1
|
package com.yohoufo.common.interceptor;
|
1
|
package com.yohoufo.common.interceptor;
|
2
|
|
2
|
|
3
|
-import com.google.common.collect.ImmutableList;
|
|
|
4
|
-import com.netflix.config.DynamicPropertyFactory;
|
|
|
5
|
-import com.yoho.core.common.utils.MD5;
|
|
|
6
|
-import com.yoho.core.config.ConfigReader;
|
|
|
7
|
-import com.yoho.error.event.LogEvent;
|
|
|
8
|
-import com.yohoufo.common.annotation.IgnoreSignature;
|
|
|
9
|
-import com.yohoufo.common.exception.SignatureNotMatchException;
|
|
|
10
|
-import com.yohoufo.common.utils.MD5Util;
|
|
|
11
|
-import com.yohoufo.common.utils.ServletUtils;
|
3
|
+import java.lang.reflect.Method;
|
|
|
4
|
+import java.net.InetAddress;
|
|
|
5
|
+import java.net.UnknownHostException;
|
|
|
6
|
+import java.util.Arrays;
|
|
|
7
|
+import java.util.LinkedList;
|
|
|
8
|
+import java.util.List;
|
|
|
9
|
+import java.util.Map;
|
|
|
10
|
+
|
|
|
11
|
+import javax.annotation.Resource;
|
|
|
12
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
13
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
14
|
+
|
12
|
import org.apache.commons.lang.StringUtils;
|
15
|
import org.apache.commons.lang.StringUtils;
|
13
|
import org.slf4j.Logger;
|
16
|
import org.slf4j.Logger;
|
14
|
import org.slf4j.LoggerFactory;
|
17
|
import org.slf4j.LoggerFactory;
|
|
@@ -18,23 +21,17 @@ import org.springframework.web.method.HandlerMethod; |
|
@@ -18,23 +21,17 @@ import org.springframework.web.method.HandlerMethod; |
18
|
import org.springframework.web.servlet.HandlerInterceptor;
|
21
|
import org.springframework.web.servlet.HandlerInterceptor;
|
19
|
import org.springframework.web.servlet.ModelAndView;
|
22
|
import org.springframework.web.servlet.ModelAndView;
|
20
|
|
23
|
|
21
|
-import javax.annotation.Resource;
|
|
|
22
|
-import javax.crypto.Mac;
|
|
|
23
|
-import javax.crypto.spec.SecretKeySpec;
|
|
|
24
|
-import javax.servlet.http.HttpServletRequest;
|
|
|
25
|
-import javax.servlet.http.HttpServletResponse;
|
|
|
26
|
-import java.lang.reflect.Method;
|
|
|
27
|
-import java.net.InetAddress;
|
|
|
28
|
-import java.net.UnknownHostException;
|
|
|
29
|
-import java.util.*;
|
24
|
+import com.yoho.core.config.ConfigReader;
|
|
|
25
|
+import com.yoho.error.event.LogEvent;
|
|
|
26
|
+import com.yoho.signature.MsgSign;
|
|
|
27
|
+import com.yohoufo.common.annotation.IgnoreSignature;
|
|
|
28
|
+import com.yohoufo.common.exception.SignatureNotMatchException;
|
|
|
29
|
+import com.yohoufo.common.utils.ServletUtils;
|
30
|
|
30
|
|
31
|
public class SignatureVerifyInterceptor implements HandlerInterceptor, ApplicationEventPublisherAware {
|
31
|
public class SignatureVerifyInterceptor implements HandlerInterceptor, ApplicationEventPublisherAware {
|
32
|
|
32
|
|
33
|
private final Logger logger = LoggerFactory.getLogger(SignatureVerifyInterceptor.class);
|
33
|
private final Logger logger = LoggerFactory.getLogger(SignatureVerifyInterceptor.class);
|
34
|
|
34
|
|
35
|
- //验签算法
|
|
|
36
|
- private final static String VERIFY_ARITHMETIC = "HmacSHA256";
|
|
|
37
|
-
|
|
|
38
|
//客户端加签请求头
|
35
|
//客户端加签请求头
|
39
|
private final static String HTTP_HEADER_VERIFY_DATA = "x-yoho-verify";
|
36
|
private final static String HTTP_HEADER_VERIFY_DATA = "x-yoho-verify";
|
40
|
|
37
|
|
|
@@ -74,20 +71,18 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
|
@@ -74,20 +71,18 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
74
|
if(this.validateReqParams(httpServletRequest, params)){
|
71
|
if(this.validateReqParams(httpServletRequest, params)){
|
75
|
return true;
|
72
|
return true;
|
76
|
}
|
73
|
}
|
77
|
-
|
|
|
78
|
- //(4) 预留后门, 如果是内网并且传入_sncp参数, 并且验证成功, 不验证.
|
|
|
79
|
- String temporaryValueQeq = params.get("_sncp"); //请求的预留后门的值
|
|
|
80
|
- String temporaryValue = configReader.getString("gateway.client.secret.h5", "");
|
|
|
81
|
- logger.debug("SignatureVerifyInterceptor. method is {}, temporaryValueQeq is {}, temporaryValue is {} and isInner is {}", method, temporaryValueQeq, temporaryValue);
|
|
|
82
|
- if (!StringUtils.isEmpty(temporaryValueQeq) && !StringUtils.isEmpty(temporaryValue) && temporaryValueQeq.trim().equals(temporaryValue.trim()) && isInnerIp(httpServletRequest)){
|
74
|
+
|
|
|
75
|
+ //(4) 验证参数
|
|
|
76
|
+ MsgSign msgSign = new MsgSign();
|
|
|
77
|
+ if (msgSign.paramVerify(params) && isInnerIp(httpServletRequest,false)){
|
83
|
return true;
|
78
|
return true;
|
84
|
}
|
79
|
}
|
85
|
|
80
|
|
86
|
//(4) 验证消息签名.
|
81
|
//(4) 验证消息签名.
|
87
|
- String message = this.getPramsString(params);
|
82
|
+ String message = msgSign.getPramsString(params);
|
88
|
String verifyMessage = httpServletRequest.getHeader(HTTP_HEADER_VERIFY_DATA);
|
83
|
String verifyMessage = httpServletRequest.getHeader(HTTP_HEADER_VERIFY_DATA);
|
89
|
logger.debug("verifySignature: message is {}, verifyMessage is {}", message, verifyMessage);
|
84
|
logger.debug("verifySignature: message is {}, verifyMessage is {}", message, verifyMessage);
|
90
|
- boolean verifyRes = this.verifySignatureNew(udid, message, verifyMessage);
|
85
|
+ boolean verifyRes = msgSign.verifySign(udid, message, verifyMessage, false, appVersion);
|
91
|
logger.debug("verifySignature: message is {}, verifyMessage is {}, res is {}", message, verifyMessage, verifyRes);
|
86
|
logger.debug("verifySignature: message is {}, verifyMessage is {}, res is {}", message, verifyMessage, verifyRes);
|
92
|
|
87
|
|
93
|
if(!verifyRes){
|
88
|
if(!verifyRes){
|
|
@@ -172,7 +167,7 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
|
@@ -172,7 +167,7 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
172
|
private boolean validateReqParams(HttpServletRequest request, Map<String, String> params){
|
167
|
private boolean validateReqParams(HttpServletRequest request, Map<String, String> params){
|
173
|
//内网访问的pc/h5不作校验
|
168
|
//内网访问的pc/h5不作校验
|
174
|
String clientType = params.get("client_type");
|
169
|
String clientType = params.get("client_type");
|
175
|
- if(("web".equals(clientType) || "h5".equals(clientType) || "wechat".equals(clientType)) && isInnerIp(request)){
|
170
|
+ if(("web".equals(clientType) || "h5".equals(clientType) || "wechat".equals(clientType)) && isInnerIp(request, true)){
|
176
|
return true;
|
171
|
return true;
|
177
|
}
|
172
|
}
|
178
|
//是否校验全部接口,开关-true:校验全部接口(除含@IgnoreSignature注解接口) 开关-false:只校验核心接口
|
173
|
//是否校验全部接口,开关-true:校验全部接口(除含@IgnoreSignature注解接口) 开关-false:只校验核心接口
|
|
@@ -193,12 +188,13 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
|
@@ -193,12 +188,13 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
193
|
/**
|
188
|
/**
|
194
|
* 是否内网ip
|
189
|
* 是否内网ip
|
195
|
* @param request
|
190
|
* @param request
|
|
|
191
|
+ * @param 是否强制验证
|
196
|
* @return
|
192
|
* @return
|
197
|
*/
|
193
|
*/
|
198
|
- public boolean isInnerIp(HttpServletRequest request){
|
194
|
+ public boolean isInnerIp(HttpServletRequest request, boolean enFlag){
|
199
|
//增加内网ip验证开关,供压测时使用
|
195
|
//增加内网ip验证开关,供压测时使用
|
200
|
boolean isInnerIpVerifyEnable = configReader.getBoolean("gateway.security.isInnerIpVerifyEnable", true);
|
196
|
boolean isInnerIpVerifyEnable = configReader.getBoolean("gateway.security.isInnerIpVerifyEnable", true);
|
201
|
- if(!isInnerIpVerifyEnable){
|
197
|
+ if(!isInnerIpVerifyEnable && !enFlag){
|
202
|
return true;
|
198
|
return true;
|
203
|
}
|
199
|
}
|
204
|
String ip = getRemoteIP( request );
|
200
|
String ip = getRemoteIP( request );
|
|
@@ -243,31 +239,6 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
|
@@ -243,31 +239,6 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
243
|
return ServletUtils.getRequestParams(httpServletRequest);
|
239
|
return ServletUtils.getRequestParams(httpServletRequest);
|
244
|
}
|
240
|
}
|
245
|
|
241
|
|
246
|
- /**
|
|
|
247
|
- * 拼接请求参数,k1=v1&k2=v2
|
|
|
248
|
- * @param reqParams
|
|
|
249
|
- * @return
|
|
|
250
|
- */
|
|
|
251
|
- private String getPramsString(Map<String, String> reqParams) {
|
|
|
252
|
- ImmutableList list = ImmutableList.of();
|
|
|
253
|
- SortedMap<String, String> filtedMap = new TreeMap<>();
|
|
|
254
|
- for (Map.Entry<String, String> entry : reqParams.entrySet()) {
|
|
|
255
|
- String k = entry.getKey();
|
|
|
256
|
- if (!list.contains(k)) {
|
|
|
257
|
- filtedMap.put(k, entry.getValue());
|
|
|
258
|
- }
|
|
|
259
|
- }
|
|
|
260
|
- //string: k1=v1&k2=v2
|
|
|
261
|
- List<String> array = new LinkedList<>();
|
|
|
262
|
- for (Map.Entry<String, String> entry : filtedMap.entrySet()) {
|
|
|
263
|
- String pair = entry.getKey() + "=" + entry.getValue();
|
|
|
264
|
- array.add(pair.trim());
|
|
|
265
|
- }
|
|
|
266
|
- String paramStr = String.join("&", array);
|
|
|
267
|
- logger.debug("getRequestInfo: param str is: {}", paramStr);
|
|
|
268
|
- return paramStr;
|
|
|
269
|
- }
|
|
|
270
|
-
|
|
|
271
|
|
242
|
|
272
|
/**
|
243
|
/**
|
273
|
* 验证签名
|
244
|
* 验证签名
|
|
@@ -276,25 +247,25 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
|
@@ -276,25 +247,25 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
276
|
* @param verifyMessage
|
247
|
* @param verifyMessage
|
277
|
* @return
|
248
|
* @return
|
278
|
*/
|
249
|
*/
|
279
|
- private boolean verifySignatureNew(String udid, String message, String verifyMessage){
|
|
|
280
|
- //(1) 验证信息为空或者udid为空,直接返回
|
|
|
281
|
- if(StringUtils.isEmpty(verifyMessage) || StringUtils.isEmpty(udid)){
|
|
|
282
|
- return false;
|
|
|
283
|
- }
|
|
|
284
|
- //(2) 获取秘钥
|
|
|
285
|
- String md5Salt = DynamicPropertyFactory.getInstance().getStringProperty("gateway.signature.key.salt", "mQyMTMwZjlmZTZmYjY4UjkNmYwZGM0OTk0Y").get();
|
|
|
286
|
- String encryptStr = udid + md5Salt;
|
|
|
287
|
- //对udid加盐后二次md5
|
|
|
288
|
- String signatureKey = MD5.md5(MD5.md5(encryptStr));
|
|
|
289
|
-
|
|
|
290
|
- //(3) 对消息加签
|
|
|
291
|
- String signatureRes = this.HmacSHA256(message, signatureKey);
|
|
|
292
|
- if(verifyMessage.equals(signatureRes)){
|
|
|
293
|
- return true;
|
|
|
294
|
- }
|
|
|
295
|
- logger.warn("verifySignatureNew: signature verify failed: message is {}, verifyMessage is {}, udid is {}, key is {}", message, verifyMessage, udid, signatureKey);
|
|
|
296
|
- return false;
|
|
|
297
|
- }
|
250
|
+// private boolean verifySignatureNew(String udid, String message, String verifyMessage){
|
|
|
251
|
+// //(1) 验证信息为空或者udid为空,直接返回
|
|
|
252
|
+// if(StringUtils.isEmpty(verifyMessage) || StringUtils.isEmpty(udid)){
|
|
|
253
|
+// return false;
|
|
|
254
|
+// }
|
|
|
255
|
+// //(2) 获取秘钥
|
|
|
256
|
+// String md5Salt = DynamicPropertyFactory.getInstance().getStringProperty("gateway.signature.key.salt", "mQyMTMwZjlmZTZmYjY4UjkNmYwZGM0OTk0Y").get();
|
|
|
257
|
+// String encryptStr = udid + md5Salt;
|
|
|
258
|
+// //对udid加盐后二次md5
|
|
|
259
|
+// String signatureKey = MD5.md5(MD5.md5(encryptStr));
|
|
|
260
|
+//
|
|
|
261
|
+// //(3) 对消息加签
|
|
|
262
|
+// String signatureRes = this.HmacSHA256(message, signatureKey);
|
|
|
263
|
+// if(verifyMessage.equals(signatureRes)){
|
|
|
264
|
+// return true;
|
|
|
265
|
+// }
|
|
|
266
|
+// logger.warn("verifySignatureNew: signature verify failed: message is {}, verifyMessage is {}, udid is {}, key is {}", message, verifyMessage, udid, signatureKey);
|
|
|
267
|
+// return false;
|
|
|
268
|
+// }
|
298
|
|
269
|
|
299
|
/**
|
270
|
/**
|
300
|
* 签名失败上报事件
|
271
|
* 签名失败上报事件
|
|
@@ -312,26 +283,26 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
|
@@ -312,26 +283,26 @@ public class SignatureVerifyInterceptor implements HandlerInterceptor, Applicati |
312
|
}
|
283
|
}
|
313
|
}
|
284
|
}
|
314
|
|
285
|
|
315
|
- /**
|
|
|
316
|
- * 使用hmac加密
|
|
|
317
|
- * @param data
|
|
|
318
|
- * @param secret
|
|
|
319
|
- * @return
|
|
|
320
|
- */
|
|
|
321
|
- private String HmacSHA256(String data, String secret){
|
|
|
322
|
- String res = null;
|
|
|
323
|
- try{
|
|
|
324
|
- Mac sha256_HMAC = Mac.getInstance(VERIFY_ARITHMETIC);
|
|
|
325
|
- SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), VERIFY_ARITHMETIC);
|
|
|
326
|
- sha256_HMAC.init(secret_key);
|
|
|
327
|
- byte[] encryptByte = sha256_HMAC.doFinal(data.getBytes());
|
|
|
328
|
- res = MD5Util.byteArrayToHexString(encryptByte);
|
|
|
329
|
- logger.debug("HmacSHA256: data is {}, secret is {}, res is {}", data, secret, res);
|
|
|
330
|
- }catch (Exception e){
|
|
|
331
|
- logger.warn("HmacSHA256: hmac failed, data is {}, error is {}", data, e);
|
|
|
332
|
- }
|
|
|
333
|
- return res;
|
|
|
334
|
- }
|
286
|
+// /**
|
|
|
287
|
+// * 使用hmac加密
|
|
|
288
|
+// * @param data
|
|
|
289
|
+// * @param secret
|
|
|
290
|
+// * @return
|
|
|
291
|
+// */
|
|
|
292
|
+// private String HmacSHA256(String data, String secret){
|
|
|
293
|
+// String res = null;
|
|
|
294
|
+// try{
|
|
|
295
|
+// Mac sha256_HMAC = Mac.getInstance(VERIFY_ARITHMETIC);
|
|
|
296
|
+// SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), VERIFY_ARITHMETIC);
|
|
|
297
|
+// sha256_HMAC.init(secret_key);
|
|
|
298
|
+// byte[] encryptByte = sha256_HMAC.doFinal(data.getBytes());
|
|
|
299
|
+// res = MD5Util.byteArrayToHexString(encryptByte);
|
|
|
300
|
+// logger.debug("HmacSHA256: data is {}, secret is {}, res is {}", data, secret, res);
|
|
|
301
|
+// }catch (Exception e){
|
|
|
302
|
+// logger.warn("HmacSHA256: hmac failed, data is {}, error is {}", data, e);
|
|
|
303
|
+// }
|
|
|
304
|
+// return res;
|
|
|
305
|
+// }
|
335
|
|
306
|
|
336
|
//含忽略签名校验注解的接口,不验证
|
307
|
//含忽略签名校验注解的接口,不验证
|
337
|
private boolean isVerifySignature(HandlerMethod handlerMethod, String clientType, String appVersion){
|
308
|
private boolean isVerifySignature(HandlerMethod handlerMethod, String clientType, String appVersion){
|