接入说明
基本配置
基本配置/ 填写服务器配置中提交下面三个参数
- url
- token
- EncodingAESKey
- 消息加密方式
重点是url和token。
- url指定后,原先发送到微信官方服务器的请求会转发到指定的url,也就是我们自己的服务器上。
- token是我们自定义的字符串,用于身份验证,稍后详述。
安全验证目的
我们制定url后,可以把网页登录账号的公众号消息转发我们台服务器切换,这里面涉及一个安全问题。
- 你不能转发给第三方公众号的服务器。微信官方也要确认你绑定的服务器所有者是你自己。
- 开发者也要确认接收到的请求确认来自微信官方。
为了达到此目的,于是有了服务器验证的过程。
服务器验证
当点击提交时,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示
- signature 加密签名
- timestamp 时间戳
- nonce 随机数
- echostr 随机字符
注:signature加密签名是有微信官方根据(timestamp+nonce+token)三个参数,按照签名算法(算法A)计算后得到。
验证逻辑以及参数的意义。
以上我们用到了包含token在内的5个参数,真的有必要这么多参数吗?这里我来分析一下。
如何验证请求来自官方
signature=算法sha1(timestamp+token+nonce)
这里token只有你和微信官方知道,所以你在服务器上用相同的算得出signature,这个结果等于微信给你的signature。就是可以说明发来请求的人掌握了token的值,这个人就是微信官方。timestamp和nonce都是随机数,用来混淆内容。
如何确认服务器是公众号本人。
很简单,微信在请求中放了一个暗号echostr,如果你把这个暗号回复给微信请求。微信收到后,就知道了这个暗号只有你有,所以是本人。
通过以上这么多过程就完成了双方身份的验证,提交按钮才可以通过。
拟人版验证过程
你和微信地下互相写信,首先你告诉微信“hello2019”。有一天你收到一封信,虽然没名字,但是你看到上面写着“hello2019”,你就知道这个信是微信发给你的。
你打开信封后,里面写着“niubi2018”,你回信的时候把这个代码写到信封上。微信收到回信后看到信封就知道这个信是你写的,不是被人。
因为这个过程两个代码只有你俩知道。这两个代码分别是token和echostr
java代码
接收get请求
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String signature = req.getParameter("signature");
String timestamp = req.getParameter("timestamp");
String nonce = req.getParameter("nonce");
String echostr = req.getParameter("echostr");
System.out.println(echostr);
PrintWriter out = resp.getWriter();
if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
System.out.println("验证通过");
}
}
public class CheckUtil {
private static String token ="hello2019"; //这里要和web配置的一致
public static boolean checkSignature (String signature,String timestamp,String nonce){
String [] arr = new String[]{token,timestamp,nonce};
//sort
Arrays.sort(arr);
//create string
StringBuffer content = new StringBuffer();
for(int i =0;i<arr.length;i++){
content.append(arr[i]);
}
// sha1 encryption
String tmp = getSha1(content.toString());
//compare with the singature got from weichat server
return tmp.equals(signature);
}
//sh1算法
public static String getSha1(String str){
if (null == str || 0 == str.length()){
return null;
}
char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
mdTemp.update(str.getBytes("UTF-8"));
byte[] md = mdTemp.digest();
int j = md.length;
char[] buf = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
buf[k++] = hexDigits[byte0 & 0xf];
}
return new String(buf);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}