我们有RESTful JSON端点服务于AJAX请求,希望支持跨源资源共享。我们正在锁定以确保我们不必担心跨站点请求伪造(CSRF)攻击。我们使用的方法的一部分是检查Origin标头的存在,并验证它是否包含在已批准的Origins的白名单中。但是,我们注意到某些浏览器(其中包括Chrome和Safari)包含带有AJAX POST请求的Origin标头,即使源自同一域(因此不是CORS请求)。
由于我们不希望我们的用户必须将提供REST端点的相同域列入白名单,因此我们希望自动确定给定请求是“相同域”还是“交叉源” 。要做到这一点,现在我们最好的尝试是监视Origin标头的存在,如果存在,则将其与Host标头的值进行比较。我们的逻辑是,如果Origin与Host匹配,那么此请求必须是“Same Domain”,因此我们不需要在白名单中检查Origin。
以下是我们正在考虑使用的服务器端JS代码片段:
if (typeof (headers["Origin"]) !== "undefined" &&
headers["Origin"].replace(new RegExp("^.*?//"), "") !== headers["Host"] &&
!contains(allowedOrigins, headers.Origin) ) {
return false;
} else {
return true;
}
需要正则表达式比较,因为Origin标题将如下所示:
http://localhost:8080
而主机标题将如下所示:
localhost:8080
因此,我使用该正则表达式删除了前导的http://。
问题是我们还没有看到使用或讨论这种方法的任何其他实现。这让我们担心,由于某种原因,这可能不是一种合适的方法。所以,问题是 - 正在比较Host标头和Origin标头,以确定请求是否来自同一个域的安全方式?
另外,正如我所示,从原点删除了前导协议://总是会产生与主机相关的正确值吗?
答案 0 :(得分:2)
我建议您检查Ajax标头: X-Requested-With:XMLHttpRequest
同源Ajax可以添加自定义标头,几乎所有流行的框架,如jQuery都添加了X-Requested-With:XMLHttpRequest。
但是对于CORS,自定义标头会引发飞行前的HTTP OPTIONS请求。
因此,如果您在没有预先飞行的情况下看到X-Requested-With:XMLHttpRequest(或任何其他自定义标头),您就会知道它是一个同源Ajax调用。
答案 1 :(得分:0)
如果您希望在线下切换到HTTPS ,那么您当前将Host标头与Origin标头进行比较以确定相同来源的方法将失败,或者我们可以说交叉协议请求强>
就像你的代码会将这两个来源一样对待。
Origin : http://www.example.com
Origin : https://example.com
其他方法将使用 HTTP Referer标题。但我不喜欢使用它,因为欺骗它并不是一项不可能完成的任务。
我的建议是更好的安全而不是抱歉。在允许的起源列表中添加额外的项目不会给你带来太大的痛苦。