如何阻止来自节点中不同来源的发布请求

时间:2014-06-14 08:47:33

标签: javascript ruby-on-rails node.js cors

我正在阅读本教程以构建节点api:

http://scotch.io/tutorials/javascript/build-a-restful-api-using-node-and-express-4

他们将了解如何使用getpostman.com测试发布请求。

但是 - 我不希望我的应用程序响应来自不同域的发布请求。我只希望它响应来自我的域(而不是浏览器)的Rails的发布请求。如何停止接受来自外国来源的这些请求,但允许来自我的rails服务器的请求?

我尝试从this链接找到的中间件,如下所示。但是没有用。这很容易。有线索吗?

router.all('/', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "https://www.example.com");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  res.header("Access-Control-Allow-Methods", "POST GET");
  res.header("X-Frame-Options", "ALLOWALL");
  res.header("Access-Control-Allow-Credentials", "true");
  next();
 });

1 个答案:

答案 0 :(得分:6)

您可以通过将客户端的IP检查为described here来检查请求的来源。然后,您可以将其与允许的地址列表进行比较,或者执行反向DNS查找以检查域。应该仔细实施后一种方法,首先解析允许的域并检查一组静态IP地址可能会更好。

这是一个小模块,可以导出一个中间件,它可以完全执行(甚至不测试一次)。

// allowed is an array of allowed hosts
// readyCb is an optional function that will be called
// once all host names have been resolved
module.exports = function(allowed, readyCb) {
  // Resolve all domains
  var ips = [];
  var remaining = allowed.length;
  allowed.forEach(function(host) {
    if(/^[.0-9]+$/.test(host)) {
      // Should be an IP address
      ips.push(host);
      remaining--;
      if(!remaining && readyCb) readyCb();
    } else {
      // Resolve the host name
      // Adapt this if you want IPv6 support
      require('dns').resolve(host, 'A', function(err, addresses) {
        remaining--;
        if(!err) {
          addresses.forEach(function(ip) { ips.push(ip); });
        } else {
          // Handle the error, either using an additional callback
          // or by collecting all errors and submitting them to
          // readyCb
        }
        if(!remaining && readyCb) readyCb();
      });
    }
  });
  return function(req, res, next) {
    var clientIp = req.ip;
    // Check if the address is allowed
    if(ips.indexOf(clientIp) == -1) {
      res.end(403, 'Remote host is not allowed to use the API');
    } else {
      next();
    }
  };
};

浏览器请求的原始答案

使用这样的中间件:

var url = require('url'); // standard node module

function(req, res, next) {
  var ref = req.headers.referer;
  if(ref) {
    // We got a referer
    var u = url.parse(ref);
    if(u && u.hostname === 'myhost.com') {
      // Correct host, process the request
      return next();
    }
  }
  // Send some kind of error
  res.send(403, 'Invalid origin');
}

请注意,referer标头可能不可用。调整上面的代码片段以对这种情况作出反应。