-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathWeChatMessageController.java
More file actions
136 lines (123 loc) · 5.01 KB
/
WeChatMessageController.java
File metadata and controls
136 lines (123 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package net.jlxxw.wechat.web.controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.jlxxw.wechat.event.component.EventBus;
import net.jlxxw.wechat.properties.WeChatProperties;
import net.jlxxw.wechat.log.util.LoggerUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
* 微信入口核心控制器
*
* @author chunyang.leng
* @date 2021/1/20 12:48 下午
*/
@RestController
public class WeChatMessageController {
private static final Logger logger = LoggerFactory.getLogger(WeChatMessageController.class);
@Autowired
private EventBus eventBus;
@Autowired
private WeChatProperties weChatProperties;
/**
* 微信信息核心转发入口
*
* @param request 用于获取微信传递的数据信息
* @param response 用于向微信写入应答数据信息
* @throws Exception
*/
@RequestMapping(value = "${wechat.event.server.web.core-controller-url:/weChat}",method= {RequestMethod.POST,RequestMethod.GET})
public String coreController(HttpServletRequest request, HttpServletResponse response) throws Exception {
String method = request.getMethod();
if ("get".equalsIgnoreCase(method)) {
// 验证签名
response.setCharacterEncoding("UTF-8");
return verifyToken(request);
}
if ("post".equalsIgnoreCase(method)) {
try (InputStream inputStream = request.getInputStream()) {
byte[] bytes = IOUtils.toByteArray(inputStream);
String uri = request.getRequestURI();
String string = request.getQueryString();
response.setCharacterEncoding("UTF-8");
// web 模式中使用同步处理方式处理数据内容,防止线程资源滥用
return eventBus.dispatcher(bytes, uri + "?" + string);
}
}
logger.error("收到了未知请求,method:{}",method);
return "error";
}
private String verifyToken(HttpServletRequest request) throws NoSuchAlgorithmException {
String msgSignature = request.getParameter("signature");
String msgTimestamp = request.getParameter("timestamp");
String msgNonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
LoggerUtils.info(logger,"接收到微信请求:signature={},timestamp={},nonce={},echostr={}", msgSignature, msgTimestamp, msgNonce, echostr);
if (verify(msgSignature, msgTimestamp, msgNonce)) {
LoggerUtils.info(logger,"验证通过");
return echostr;
}
LoggerUtils.info(logger,"验证失败");
return "";
}
/**
* 验证Token
*
* @param msgSignature 签名串,对应URL参数的signature
* @param timeStamp 时间戳,对应URL参数的timestamp
* @param nonce 随机串,对应URL参数的nonce
* @return 是否为安全签名
*/
private boolean verify(String msgSignature, String timeStamp, String nonce) throws NoSuchAlgorithmException {
String signature = sha1Sign(weChatProperties.getVerifyToken(), timeStamp, nonce);
if (!signature.equals(msgSignature)) {
throw new RuntimeException("token认证失败");
}
return true;
}
/**
* 进行 sha1 签名运算
* @param token 项目中配置的 微信验证token
* @param timestamp 时间戳
* @param nonce 随机字符串
* @return
* @throws NoSuchAlgorithmException
*/
private static String sha1Sign(String token, String timestamp, String nonce) throws NoSuchAlgorithmException {
if (StringUtils.isBlank(token)) {
throw new IllegalArgumentException("verify-token不能为空");
}
String[] array = new String[]{token, timestamp, nonce};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 3; i++) {
sb.append(array[i]);
}
String str = sb.toString();
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
return hexstr.toString();
}
}