微信服务器IP地址详解,并判断该地址是否来自微信

来源:互联网 发布:用idle打开python文件 编辑:程序博客网 时间:2024/06/06 14:18

公众号官网说明:点击进去官方文档

如果公众号基于消息接收安全上的考虑,需要获知微信服务器的IP地址列表,以便识别出哪些消息是微信官方推送给你的,哪些消息可能是他人伪造的,可以通过该接口获得微信服务器IP地址列表。

接口调用请求说明

http请求方式: GEThttps://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.1"]}
参数说明ip_list微信服务器IP地址列表

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):

{"errcode":40013,"errmsg":"invalid appid"}

企业号官网说明:点击进去官方文档

获取微信服务器的ip段

  • 请求说明

Https请求方式: GET

https://qyapi.weixin.qq.com/cgi-bin/getcallbackip?access_token=ACCESS_TOKEN

  • 参数说明
参数必须说明access_token是调用接口凭证
  • 返回结果
{   "ip_list": ["101.226.103.*", "101.226.62.*"]}



把自己公众号的accesstoken 替换请求地址的ACCESS_TOKEN,然后get请求就可以换取到服务器的ip地址列表了,

但是有一些需要注意的地方(请看返回数据下面的内容);

公证号的ipv4地址段
{
"ip_list": [

"101.226.62.77",
"101.226.62.78",
"101.226.62.79",
···
"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"]
}
企业号的ipv4地址段
{
"ip_list": [

"101.226.103.*",
"101.226.125.*",
"101.226.62.*",
"103.7.30.*",
"112.5.138.*",
"112.90.78.*",
"117.135.171.*",
"120.198.199.*",
"140.207.54.*",
"183.61.32.*",
"203.205.167.*"]
}

请注意:

在返回的数据的地址数据中,公众号中有"101.226.103.0\/25",其中的\/是转义字符/,该地址就是"101.226.103.0/25" ,也就是说这是一个带有子网掩码的ip地址;

打印来自微信的请求头

host:你的服务器网址
user-agent:Mozilla/4.0
content-length:534
accept:*/*
cache-control:no-cache
content-type:text/xml
pragma:no-cache
x-real-ip:58.247.206.153

所以我们不能通过request.getRemoteAddr()获取微信请求的地址,

所以通过request.getHeader("x-real-ip");


同时你也应该发现ip地址58.247.206.153并没有在上面获取的ip地址列表里面

这是觉需要去利用那些带有子网掩码的ip地址了,

/** * 判断目标ip是否属于某个ip子网 * @param subIp带有子网掩码的ip * @param ip目标ip * @return成功true,失败false */private static boolean isSubnet(String subIp, String ip) {String[] subs = subIp.split("/");int[] subnetMask = getSubnetMask(Integer.parseInt(subs[1]));int[] ipArray = getIpv4Array(subs[0]);String subnet = getSubnet(subnetMask,ipArray);int[] ipArray2 = getIpv4Array(ip);String subnet2 = getSubnet(subnetMask, ipArray2);if (subnet.equals(subnet2))return true;return false;}/** * 获取子网掩码数组 * @param num子网掩码长(暨带子网掩码的ip/后面的数字) * @return长度为4的int数组 */private static int[] getSubnetMask(int num) {int[] masks = new int[4];int index = num / 8;int remainder = num % 8;String remainderToBinary = "";for (int i = 0; i < index; i++)masks[i] = 255;for (int i = 0; i < 8; i++) {int j = 0;if (i < remainder)j = 1;remainderToBinary = remainderToBinary + j;}int sublast = Integer.valueOf(remainderToBinary, 2);masks[index] = sublast;if (index < masks.length - 1) {for (int i = index + 1; i < masks.length; i++)masks[i] = 0;}return masks;}/** * 分解ip地址 * @param ipip地址 * @return长度为4的int数组 */private static int[] getIpv4Array(String ip) {int[] ipArray = new int[4];String[] ips = ip.split("\\.");for (int i = 0; i < ips.length; i++) ipArray[i] = Integer.parseInt(ips[i]);return ipArray;}/** * 通过子网掩码数组和,ip地址数组获取主机地址 * @param masks子网掩码数组 * @param ipArrayip数组 * @return主机地址 */private static String getSubnet(int[] masks, int[] ipArray) {String subnet = "";if (masks.length != ipArray.length) {try {throw new Exception("子网掩码长度和ip地址长度不一样");} catch (Exception e) {e.printStackTrace();}}for (int i = 0; i < ipArray.length; i++) {int and = masks[i] & ipArray[i];subnet = subnet + and;if (i < ipArray.length -1) subnet = subnet + ".";}return subnet;}


所以,那些带掩码的ip,代表的是在该主机下的所有地址,/25,表示有128个地址,这时就需要计算来得到,而不是简单的字符串匹配!


企业号的就号很多,全部是.*,所以只需要判断前3个数字就可以了!






3 0