跨域资源共享(CORS)和Javascript

7
作为一个例子,我们来看一下这个URL:http://api.duckduckgo.com/?q=computer&format=json(此服务器未启用CORS!)。
  1. We can access the contents from this URL from any popular browser as a normal URL, browser has no issues opening this URL nor the server returns any error.

  2. A server-side language like PHP/RoR can fetch the contents from this URL without adding any additional headers or special server settings. I used following PHP code and it simply worked.

    $url='http://api.duckduckgo.com/?q=computer&format=json';
    $json = file_get_contents($url);
    echo $json;
    
  3. I just started working in javascript framework, AngularJS. I used following code...

    delete $http.defaults.headers.common['X-Requested-With'];
    var url="http://api.duckduckgo.com/?q=computer&format=json";
    $http.get(url)
         .success(function(data) {
             $scope.results=data;
          })
    

    With above AngularJS code, I received following error:

    XMLHttpRequest cannot load http://api.duckduckgo.com/?q=computer&format=json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.

  4. AngularJS uses JQuery so I tried the same in JQuery with following code:

    var url="http://api.duckduckgo.com/?q=computer&format=json";
    $.getJSON(url , function( data ) {
        console.log(data);
    });
    

    This also produced the same error as did AngularJS code.

  5. Then my further research brought me to the point that it's actually not specific to JQuery and AngularJS. Both of these inherit this issue from Javascript!



所以我的问题不是什么是CORS。我的问题是:

  1. 我理解的是,无论是Web浏览器还是PHP/RoR或JavaScript框架,都通过相同的HTTP或HTTPS请求URL,对吗?当然,是的。那么为什么当请求来自JavaScript时,HTTP必须更加安全呢?HTTP和服务器如何知道请求来自JavaScript?

  2. 当Web浏览器可以打开URL并且PHP/RoR(或任何服务器端语言)可以访问该URL而无需任何额外的设置/标头时,为什么AngularJS、JQuery(或一句话JavaScript)不能访问该URL,除非服务器为请求根设置了Access-Control-Allow-Origin标头?

  3. 有哪些特殊功能(PHP/RoR具有的功能)在JavaScript中缺失,因此它无法在可以从其地址栏无问题打开该URL的同一浏览器中访问相同的URL?

只是想提一下,我基本上是一个iOS开发人员,最近开始学习Web开发,特别是AngularJS。所以我很好奇这一切是怎么回事,为什么会这样!


7
“为什么JavaScript发起的请求要更安全?”因为Ajax请求会以用户身份进行,包括用户的cookie信息,例如用于会话等的cookie。因此,如果用户已登录且允许默认的跨域请求,那么恶意网站就可以发起一个Ajax请求获取你的银行余额和账单等敏感信息,并获得成功响应。 - Jonathan Lonowski
可能的一个原因是脚本注入,如果您是标准用户并访问某个网页,则您会信任该网页。如果该网页试图涉及另一个域,则需要您信任它,默认情况下会被拒绝而不是请求权限。(这是我个人的理解,如有错误请指正) - Nunners
作为用户,您不知道域A是否被允许与域B通信,您对那个握手[CORS]没有发言权。 - epascarello
@JonathanLonowski,了不起的发现 :) 感谢您对Ajax的快速提示! - Atif Azad
3个回答

7

出于安全考虑,它被禁用了。以下是一种情况:

  • 假设Facebook有一个需要用户验证的“发布信息到时间轴”的api。
  • 您在访问badsite.com时已登录Facebook。
  • badsite.com使用JavaScript调用Facebook api。由于浏览器正在向Facebook发出有效请求,因此发送了您的身份验证cookie,并且Facebook接受消息并在您的时间轴上发布了badsite的广告。

这对于服务器来说不是问题,因为badsite.com的服务器无法访问您的Facebook身份验证cookie,也无法代表您伪造有效请求。


是的,这很有道理! - Atif Azad
既然知道JS可以访问客户端机器上的cookies和sessions,除了CORS之外,是否还有其他已被禁用的HTTP功能?还有其他可能的安全漏洞吗? - Atif Azad
1
不太确定你在问什么,但有很多可能的安全漏洞。请查看OWASP十大安全漏洞 - Jason P

1
你记得所有的JavaScript请求都由浏览器处理。因此,浏览器检测跨域请求很容易。
与PHP / RoR相比,来自JavaScript的请求没有区别,只是被浏览器拒绝了。
服务器代码可以通过头"Access-Control-Allow-Origin"接受跨域JavaScript请求,因为在拒绝JavaScript请求之前,浏览器会向服务器发送一个"OPTIONS"请求以询问响应中的头"Access-Control-Allow-Origin"。如果值与当前来源匹配,浏览器将接受JavaScript请求并将其发送到服务器。
所有浏览器都实现了此策略Same Origin Policy

点赞指出“OPTIONS”和浏览器允许JavaScript请求的方式,谢谢 :) - Atif Azad

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接