Node.js授权微信公众号服务器访问本地(验证微信公众号IP地址)
1 概述
最近公司使用node.js进行微信公众号服务器端开发,到了接收公众号发送的事件请求并回复的模块,需要验证微信服务器地址进而增加安全性。微信公众号也为我们提供了获取IP地址列表或者IP网段信息的接口。具体文档信息如下:
如果公众号基于安全等考虑,需要获知微信服务器的IP地址列表,以便进行相关限制,可以通过该接口获得微信服务器IP地址列表或者IP网段信息。
接口调用请求说明:
请求方式:
https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=ACCESS_TOKEN
参数说明:
access_token:公众号的access_token
返回说明:
正常情况下,微信会返回下述JSON数据包给公众号:
{
"ip_list": ["127.0.0.1",
"127.0.0.2",
"101.226.103.0/25"]
}
参数说明:
ip_list:微信服务器IP地址列表
错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
{"errcode":40013,"errmsg":"invalid appid"}
根据微信接口得知要获取IP地址列表就需要先获取ACCESS_TOKEN(如何获取这里不做讲述,请见微信公众平台API文档关于如何获取access_token部分)。然后发送get请求到微信服务器,获取IP地址列表。
2 处理返回的IP地址列表
微信返回的IP地址列表如下:
{ ip_list:
[ '101.226.62.77', '101.226.62.78', '101.226.62.79', '101.226.62.80', '101.226.62.81', '101.226.62.82', '101.226.62.83', '101.226.62.84', '101.226.62.85', '101.226.62.86', '101.226.103.59', '101.226.103.60', '101.226.103.61', '101.226.103.62', '101.226.103.63', '101.226.103.69', '101.226.103.70', '101.226.103.71', '101.226.103.72', '101.226.103.73', '140.207.54.73', '140.207.54.74', '140.207.54.75', '140.207.54.76', '140.207.54.77', '140.207.54.78', '140.207.54.79', '140.207.54.80', '182.254.11.203', '182.254.11.202', '182.254.11.201', '182.254.11.200', '182.254.11.199', '182.254.11.198', '59.37.97.100', '59.37.97.101', '59.37.97.102', '59.37.97.103', '59.37.97.104', '59.37.97.105', '59.37.97.106', '59.37.97.107', '59.37.97.108', '59.37.97.109', '59.37.97.110', '59.37.97.111', '59.37.97.112', '59.37.97.113', '59.37.97.114', '59.37.97.115', '59.37.97.116', '59.37.97.117', '59.37.97.118', '112.90.78.158', '112.90.78.159', '112.90.78.160', '112.90.78.161', '112.90.78.162', '112.90.78.163', '112.90.78.164', '112.90.78.165', '112.90.78.166', '112.90.78.167', '140.207.54.19', '140.207.54.76', '140.207.54.77', '140.207.54.78', '140.207.54.79', '140.207.54.80', '180.163.15.149', '180.163.15.151', '180.163.15.152', '180.163.15.153', '180.163.15.154', '180.163.15.155', '180.163.15.156', '180.163.15.157', '180.163.15.158', '180.163.15.159', '180.163.15.160', '180.163.15.161', '180.163.15.162', '180.163.15.163', '180.163.15.164', '180.163.15.165', '180.163.15.166', '180.163.15.167', '180.163.15.168', '180.163.15.169', '180.163.15.170', '101.226.103.0/25', '101.226.233.128/25', '58.247.206.128/25', '182.254.86.128/25', '103.7.30.21', '103.7.30.64/26', '58.251.80.32/27', '183.3.234.32/27', '121.51.130.64/27' ] }
获取到IP地址列表后进行比对就行了,那么如何获取请求的真实IP地址呢?
2.1 获取请求的真实IP地址
首先我们使用方法util.inspect(req.headers)打印出请求的头端所有信息如下:
{
'user-agent': 'Mozilla/4.0',
accept: '*/*',
host: 'www.xxxxxx.cn',
pragma: 'no-cache',
'content-length': '346',
'content-type': 'text/xml',
'x-real-ip': '103.7.30.68',
'x-forwarded-for': '103.7.30.68, 218.145.64.217',
proxyagent: 'oray phfw 22057'
}
其中” x-real-ip”属性就是真实的请求IP了,“x-forwarded-for”代理服务器IP,其他不做概述。使用req.header('x-real-ip')或者req.headers['x-real-ip']都可以获取到IP地址的字符串。
那么这时就用获取到的请求IP地址,和微信给我们提供的IP地址列表,进行逐一比对不就可以了么?答案是否定的。我们获取到的IP地址是:103.7.30.68然而微信返回给我们的IP地址列表里没有这个IP,但是有一个挺像的IP:103.7.30.64/26。它们有什么关系么?肯定有关系,下面我就来阐述它们的关系和如何判断。
细心的朋友可能会发现,微信为我们提供的IP地址分成了两部分,一部分是正常的IP(101.226.62.77),另外一部分是带有掩码的IP地址(103.7.30.64/26)。
2.2 什么是带掩码的IP地址
对于网络IP地址的划分非常熟悉的朋友请略过这一部分,我也是刚刚学习完成,做一下笔记。
2.2.1 IP地址
IP地址是由32位(bit)的二进制数字组成。那么划分的时候就是从032~232个主机(43个亿)。由于运算过于复杂所以划分成了4个小节,使用“.”作为区分。这样便于计算。
IP地址我们一般划分为A、B、C、D、E,5类。
类别 |
十进制 |
二进制 |
|
||
起始 |
结束 |
起始 |
结束 |
解释 |
|
主类 |
0.0.0.1 |
0.255.255.254 |
00000000. 00000000. 00000000. 00000001 |
00000000.11111111.11111111.11111110 |
用来区分分类的IP地址 |
A类 |
1.0.0.1 |
126.255.255.254 |
00000001. 00000000. 00000000. 00000001 |
01111110. 11111111. 11111111. 11111110 |
A |