如何在节点中阻止来自不同来源的发布请求
Posted
技术标签:
【中文标题】如何在节点中阻止来自不同来源的发布请求【英文标题】:how to block post request from different origin in node 【发布时间】:2014-08-04 18:34:54 【问题描述】:我正在阅读本教程以构建节点 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】:您可以通过检查客户端的 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');
请注意,引用标头可能不可用。调整上述 sn-p 以应对此类情况。
【讨论】:
每当我尝试来自 getpostman.com 或我的 rails 服务器的发布请求时,u.hostname 为空。另外,有人可以伪造主机名吗? 澄清 - 我们将从 Rails 发送发布请求,而不是直接从浏览器发送(更新问题)。以上是关于如何在节点中阻止来自不同来源的发布请求的主要内容,如果未能解决你的问题,请参考以下文章
来自除 localhost 之外的每个来源的 CORS 策略阻止的对外部 API 的 HTTP 请求
来自来源的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头
AWS - 防火墙管理器 - WAF 规则如何阻止来自 IP 地址的请求(无主机名)?