验证请求来自微信服务器

全篇共 1100 字。按500字/分钟阅读,预计用时 2.2 分钟。总访问 446 次,日访问 4 次。

基于安全考虑,获取全部微信服务器IP,以过滤并非来自微信服务器的请求。尤其是在用户向公众号发送消息时,微信服务器将消息转发给开发者的服务器,开发者应该在此时检测请求的IP是否为微信服务器。

获取可信赖IP列表

微信公众号为开发者提供了可获取全部微信服务器IP地址的接口,下面是我用Node+Express实现调用接口获取IP地址的代码,我将它封装到一个工具函数中,以备重复使用。函数的返回值是一个Promise实例,结果要么是 true,要么是 false。

// 唯一参数:待检测的IP地址
const isWechatServer = ip => {
  return new Promise(async (resolve, reject) => {
    ip = ip.split('::ffff:')[1];
    try {
      // 用access_token换取微信服务器IP列表
      const accessToken = await getAccessToken();
      const callbackip = await util.getRequest(`https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=${accessToken}`);
      const allWechatServerIp = callbackip['ip_list'];
      var isWechatServer = false;
      for (var i = 0, l = allWechatServerIp.length; i < l; i++) {
        if (allWechatServerIp[i] == ip) {
          isWechatServer = true;
          break;
        }
      }
      isWechatServer ? resolve(true) : resolve(false);
    } catch (e) {
      reject(e);
    }
  });
}

过滤IP

使用Express的中间件,过滤并非来自微信服务器的请求。我接受微信公众号消息的地址是:https://www.shuaihuajun.com/wechat_ol/,只有来自微信服务器的请求才会从这个中间件进入到下一个处理信息的中间件,非微信服务器的IP请求该地址后就会收到404的HTTP响应码。

router.use(async (req, res, next) => {
  if (!await isWechatServer(req.ip)) {
    res.sendStatus(404);
    return;
  }
  next();
});

扩展阅读: