我们有服务于 AJAX 请求的 RESTful JSON 端点,希望支持跨源资源共享。我们正在锁定一切以确保我们不必担心跨站点请求伪造 (CSRF) 攻击。我们使用的部分方法是检查 Origin header 是否存在,并验证它是否包含在已批准的 Origins 白名单中。但是,我们注意到某些浏览器(其中包括 Chrome 和 Safari)在 AJAX POST 请求中包含 Origin header ,即使来自同一域(因此不是 CORS 请求)也是如此。
由于我们不希望要求我们的用户必须将提供 REST 端点的同一域列入白名单,因此我们希望自动确定给定请求是“同一域”还是“跨域” .为此,目前我们最好的尝试是观察是否存在 Origin header ,如果存在,则将其与 Host header 的值进行比较。我们的逻辑是,如果 Origin 与 Host 匹配,则此请求必须是“相同域”,因此我们不需要检查白名单中的 Origin。
这是我们正在考虑用于实现此目的的服务器端 JS 代码片段:
if (typeof (headers["Origin"]) !== "undefined" &&
headers["Origin"].replace(new RegExp("^.*?//"), "") !== headers["Host"] &&
!contains(allowedOrigins, headers.Origin) ) {
return false;
} else {
return true;
}
正则表达式比较是必需的,因为 Origin header 会像这样进来:
http://localhost:8080
而主机 header 将如下所示:
localhost:8080
因此我使用该正则表达式去除了领先的 http://。
问题是我们还没有看到任何其他实现使用或讨论这种方法。这让我们担心,出于某种原因,这可能不是一种合适的方法。因此,问题是 - 比较 Host header 和 Origin header 是否是确定请求是否来自同一域的安全方法?
此外,是否如我所展示的那样从 Origin 中删除领先的协议(protocol)://总是会产生与 Host 相关的正确值?
最佳答案
我建议您改为检查 Ajax header : X-Requested-With:XMLHttpRequest
同源 Ajax 可以添加自定义 header ,几乎所有流行的框架(例如 jQuery)都添加了 X-Requested-With: XMLHttpRequest。
然而,对于 CORS,自定义 header 会引发飞行前 HTTP OPTIONS 请求。
因此,如果您看到没有预检的 X-Requested-With: XMLHttpRequest(或任何其他自定义 header ),您就知道这是同源 Ajax 调用。
关于ajax - 相同域请求的来源和主机 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14444914/