关于javascript:Access-Control-Allow-Origin标头如何工作?

How does Access-Control-Allow-Origin header work?

显然,我完全误解了它的语义。我想到了这样的事情:

  • 客户机从http://sitea-the origin下载javascript代码mycode.js。
  • mycode.js的响应头包含access control allow origin:http://site b,我认为这意味着mycode.js可以跨源引用站点b。
  • 客户机触发mycode.js的一些功能,这些功能反过来向http://siteb发出请求,尽管是跨源请求,但这应该很好。
  • 嗯,我错了。它根本不能这样工作。因此,我阅读了跨源资源共享,并尝试阅读W3C推荐中的跨源资源共享。

    有一件事是肯定的-我仍然不明白我应该如何使用这个标题。

    我对站点A和站点B都有完全的控制权。如何使从站点A下载的javascript代码能够使用这个头部访问站点B上的资源?

    附笔。

    我不想使用JSONP。


    Access-Control-Allow-Origin是CORS(跨源资源共享)头。

    当读取的内容从网站到网站tries B B网站的CAN发送响应到一Access-Control-Allow-Origin头告诉浏览器,访问这个网页内容是到一定的起源。(一)是一个域的起源,方法和默认端口号。b)、网站的页面是不可访问的任何其他来源;采用Access-Control-Allow-Origin头打开门是由请求访问特定的跨起源起源。

    为每个网站的页面资源的访问是想让B到B网站,网站页面的响应应该是它的标题:

    1
    Access-Control-Allow-Origin: http://siteA.com

    现代浏览器的跨域请求将不完全阻滞。如果网站的页面请求从浏览器的网站B,将实际的页面读取请求在网络级和检查,如果响应标头中的requester域允许的网站。如果网站没有得到证明,B是允许访问的网站浏览到这个网页,将触发的事件和errorXMLHttpRequest’s等的响应数据的请求的JavaScript代码。

    非简单的请求。

    什么是发生在网络层,可以解释更多的比上述的复杂点。如果请求的是一个"非简单的浏览器发送的请求,"第一"预检过程无日期"选项的请求到服务器,验证,将接受的请求。当请求是一个非方(或双方):

    • 使用HTTP GET或POST(动词比其他例如PUT、DELETE)
    • 使用非简单的请求标头的头;唯一的要求是:简单
      • Accept
      • Accept-Language
      • Content-Language
      • Content-Type(这仅仅是一个简单的时候,它的价值是application/x-www-form-urlencodedmultipart/form-data,或text/plain)

    如果服务器响应的选项报头(Access-Control-Allow-Headers预检过程与适当的反应,非简单的标题,Access-Control-Allow-Methods非简单的动词),匹配的非简单的动词和/或非简单的标题,然后在浏览器发送的请求。

    这是supposing网站想把请求发/somePage,与非Content-Typeapplication/json简单值,浏览器将请求发送到第一预检过程:

    1
    2
    3
    4
    OPTIONS /somePage HTTP/1.1
    Origin: http://siteA.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: Content-Type

    请注意,是由Access-Control-Request-MethodAccess-Control-Request-Headers由浏览器自动添加的;你不需要他们。这个选项有:《成功的响应头的预检过程

    1
    2
    3
    Access-Control-Allow-Origin: http://siteA.com
    Access-Control-Allow-Methods: GET, POST, PUT
    Access-Control-Allow-Headers: Content-Type

    当发送请求后,目前是做预检过程)是相同的,该行为是如何简单的请求处理。在其他的话,非简单的请求是成功的,是其预检过程的简单处理的请求(即,服务器必须发送一Access-Control-Allow-Origin仍然是当前的响应)。

    在当前的浏览器发送的请求。

    1
    2
    3
    4
    5
    PUT /somePage HTTP/1.1
    Origin: http://siteA.com
    Content-Type: application/json

    {"myRequestContent":"JSON is so great" }

    和服务器发送一Access-Control-Allow-Origin背,就像它会被简单的请求:

    1
    Access-Control-Allow-Origin: http://siteA.com

    基于CORS的XMLHttpRequest的ESS的理解更多一点的信息是关于非简单的要求。


    跨源请求共享-CORS(也就是跨域Ajax请求)是大多数Web开发人员可能遇到的问题,根据相同的源策略,浏览器在安全沙盒中限制客户端javascript,通常JS不能直接与来自不同域的远程服务器通信。在过去,开发人员创建了许多复杂的方法来实现跨域资源请求,最常用的方法是:

  • 使用flash/silverlight或服务器端作为"代理"进行通信带遥控器。
  • 带填充的JSON(JSONP)。
  • 将远程服务器嵌入到iframe中,并通过fragment或window.name进行通信,请参阅此处。
  • 这些棘手的方法或多或少有一些问题,例如,如果开发人员简单地"评估"它,以及上面的3,JSONP可能会导致安全漏洞,尽管它有效,但两个域之间应该建立严格的合同,既不灵活也不优雅imho:。

    W3C引入了跨源资源共享(cors)作为标准解决方案,以提供安全、灵活和推荐的标准方法来解决这个问题。

    机制

    从高层来看,我们可以简单地认为CORS是来自域A的客户机Ajax调用和托管在域B上的页面之间的契约,典型的跨源请求/响应是:

    域Ajax请求头

    1
    2
    3
    4
    5
    6
    7
    Host DomainB.com
    User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
    Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
    Accept-Language en-us;
    Accept-Encoding gzip, deflate
    Keep-Alive 115
    Origin http://DomainA.com

    域B响应头

    1
    2
    3
    4
    5
    6
    Cache-Control private
    Content-Type application/json; charset=utf-8
    Access-Control-Allow-Origin DomainA.com
    Content-Length 87
    Proxy-Connection Keep-Alive
    Connection Keep-Alive

    上面标记的蓝色部分是核心事实,"来源"请求头"表示跨来源请求或飞行前请求的来源","访问控制允许来源"响应头表示此页允许来自域A的远程请求(如果值为*表示允许来自任何域的远程请求)。

    如上所述,W3建议浏览器在提交实际的跨源HTTP请求之前实现一个"飞行前请求",简而言之,它是一个HTTP OPTIONS请求:

    1
    OPTIONS DomainB.com/foo.aspx HTTP/1.1

    如果foo.aspx支持选项http动词,它可能返回如下响应:

    1
    2
    3
    4
    5
    6
    7
    8
    HTTP/1.1 200 OK
    Date: Wed, 01 Mar 2011 15:38:19 GMT
    Access-Control-Allow-Origin: http://DomainA.com
    Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
    Access-Control-Allow-Headers: X-Requested-With
    Access-Control-Max-Age: 1728000
    Connection: Keep-Alive
    Content-Type: application/json

    只有当响应包含"访问控制允许源站"且其值为"*"或包含提交CORS请求的域时,浏览器才会通过满足此命令条件提交实际的跨域请求,并将结果缓存到"飞行前结果缓存"中。

    三年前我写了一篇关于CORS的博客:Ajax跨源HTTP请求


    这个问题有点太老了,无法回答,但我会把它贴出来,以备将来参考。

    根据这篇Mozilla开发者网络文章,

    A resource makes a cross-origin HTTP request when it requests a resource from a different domain, or port than the one which the first resource itself serves.

    enter image description here

    http://domain-a.com提供的HTML页面对http://domain-b.com/image.jpg发出SRC请求。如今,网络上的许多页面都从不同的域中加载CSS样式表、图像和脚本等资源(因此应该很酷)。

    同一原产地政策

    出于安全原因,浏览器限制从脚本内启动的跨源HTTP请求。例如,XMLHttpRequestFetch遵循相同的来源政策。因此,使用XMLHttpRequestFetch的Web应用程序只能向自己的域发出HTTP请求。

    跨源资源共享(CORS)

    为了改进Web应用程序,开发人员要求浏览器供应商允许跨域请求。

    跨源资源共享(CORS)机制为Web服务器提供跨域访问控制,从而实现安全的跨域数据传输。现代浏览器在API容器(如XMLHttpRequestFetch)中使用COR来降低跨源HTTP请求的风险。

    CORS如何工作(Access-Control-Allow-Origin头)

    维基百科:

    The CORS standard describes new HTTP headers which provide browsers and servers a way to request remote URLs only when they have permission.

    Although some validation and authorization can be performed by the server, it is generally the browser's responsibility to support these headers and honor the restrictions they impose.

    例子

  • 浏览器发送带有Origin HTTP头的OPTIONS请求。

    此头的值是为父页提供服务的域。当来自http://www.example.com的页面试图访问service.example.com中的用户数据时,将向service.example.com发送以下请求头:

    来源:http://www.example.com

  • service.example.com上的服务器可以用以下方式响应:

    • 响应中的Access-Control-Allow-Origin头(acao),指示允许哪些源站。例如:

      Access-Control-Allow-Origin: http://www.example.com

    • 如果服务器不允许跨源请求,则为错误页。

    • 带通配符的Access-Control-Allow-Origin头(acao),允许所有域:

      Access-Control-Allow-Origin: *


  • 每当我开始考虑CORS时,我对于哪个站点承载头部的直觉是错误的,正如您在问题中描述的那样。对我来说,这有助于思考同一原产地政策的目的。

    相同来源策略的目的是保护您不受Sitea.com上恶意javascript的攻击,因为您选择只与Siteb.com共享私人信息。如果没有相同的源站策略,由sitea.com作者编写的javascript可以使您的浏览器使用siteb.com的身份验证cookie向siteb.com发出请求。这样,sitea.com就可以窃取您与siteb.com共享的机密信息。

    有时候你需要跨领域工作,这就是CORS的切入点。CORS为domaina.com放宽了相同的源站策略,使用Access-Control-Allow-Origin头来列出其他受信任的域(domainb.com),这些域可以运行可以与domaina.com交互的javascript。

    要了解哪个域应该为CORS头提供服务,请考虑这一点。您访问恶意网站,其中包含一些试图向mybank.com发出跨域请求的javascript。应该由mybank.com而不是恶意网站来决定是否设置CORS头文件来放宽同一源文件策略,从而允许恶意网站的javascript与之交互。如果malicous.com可以设置自己的cors头文件,允许自己的javascript访问mybank.com,这将完全取消相同的源代码策略。

    我认为我直觉不好的原因是我在开发一个站点时的观点。它是我的站点,有我所有的javascript,因此它没有做任何恶意的事情,应该由我来指定我的javascript可以与哪些其他站点交互。实际上,我应该考虑哪些其他的网站javascript正试图与我的网站交互,我应该使用CORS来允许它们?


    如果您只想测试浏览器阻止您请求的跨域应用程序,那么您可以在不安全模式下打开浏览器并测试应用程序,而不更改代码,也不使代码不安全。从Mac OS,您可以从终端线路执行此操作:

    1
    open -a Google\ Chrome --args --disable-web-security --user-data-dir

    使用react和axios,将代理链接连接到URL并添加头,如下所示

    https://cors-anywhere.herokuapp.com/+Your API URL

    只需添加代理链接就可以了,但它也会抛出错误,导致无法再次访问。因此最好添加标题,如下所示。

    1
    2
    3
    axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
          .then(response => console.log(response:data);
      }


    我在Express 4和Node 7.4以及Angular上工作,我遇到了同样的问题我可以帮助解决这个问题:
    a)服务器端:在文件app.js中,我向所有响应提供头文件,如:

    1
    2
    3
    4
    5
    app.use(function(req, res, next) {  
          res.header('Access-Control-Allow-Origin', req.headers.origin);
          res.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");
          next();
     });

    这必须在所有路由器之前完成。
    我看到很多添加了这个标题:

    1
    2
    3
    res.header("Access-Control-Allow-Headers","*");
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

    但我不需要那个,
    b)客户端:在发送Ajax中,需要添加:"withcredentials:true",比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $http({
         method: 'POST',
         url: 'url,
         withCredentials: true,
         data : {}
       }).then(function(response){
            // code  
       }, function (response) {
             // code
       });

    祝你好运。


    1。客户机从http://sitea-the origin下载javascript代码mycode.js。

    下载的代码——你的HTML脚本标签或者JavaScript的XHR或者其他什么——来自http://sitez。当浏览器请求mycode.js时,它会发送一个origin:header,上面写着"origin:http://sitez",因为它可以看到您请求的是sitea和sitez!= SITEA。(您不能停止或干扰此操作。)

    2。mycode.js的响应头包含access control allow origin:http://site b,我认为这意味着mycode.js可以跨源引用站点b。

    不。这意味着,只有SiteB可以执行此请求。因此,您从Sitez请求mycode.js会得到一个错误,而浏览器通常不会给您任何信息。但是,如果让服务器返回a-c-a-o:sitez,则会得到mycode.js。或者,如果它发送"*",就可以了,这样就可以让所有人都进来了。或者如果服务器总是从源服务器发送字符串:header…但是…为了安全起见,如果您害怕黑客,您的服务器应该只允许来自一个短名单的来源,这是允许作出这些请求的。

    然后,mycode.js来自Sitea。当它向SiteB发出请求时,它们都是跨源的,浏览器发送origin:SiteA,SiteB必须获取SiteA,识别出它在允许请求者的短列表中,然后发送回a-c-a-o:SiteA。只有这样,浏览器才会让脚本得到这些请求的结果。


    在python中,我已经成功地使用了Flask-CORS库。它使处理CORS变得非常简单和无痛。我在下面的库文档中添加了一些代码。

    安装:

    1
    $ pip install -U flask-cors

    允许所有路由上所有域的CORS的简单示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from flask import Flask
    from flask_cors import CORS

    app = Flask(__name__)
    CORS(app)

    @app.route("/")
    def helloWorld():
      return"Hello, cross-origin-world!"

    有关更具体的示例,请参阅文档。我使用了上面的简单例子来解决CORS问题,在我构建的一个离子应用程序中,它必须访问一个单独的烧瓶服务器。


    如果您使用的是PHP,请尝试在PHP文件的beaning处添加以下代码:

    如果您使用的是localhost,请尝试以下操作:

    1
    header("Access-Control-Allow-Origin: *");

    如果您使用的是服务器等外部域,请尝试以下操作:

    1
    header("Access-Control-Allow-Origin: http://www.website.com");

    对于跨源共享,设置header:'Access-Control-Allow-Origin':'*';

    php:header('Access-Control-Allow-Origin':'*');

    节点:app.use('Access-Control-Allow-Origin':'*');

    这将允许共享不同域的内容。


    只需将以下代码粘贴到web.config文件中。

    注意,您必须将以下代码粘贴到标记下

    1
    2
    3
    4
    5
    6
    7
        <httpProtocol>  
        <customHeaders>  
           
           
           
        </customHeaders>  
      </httpProtocol>

    The Access-Control-Allow-Origin response header indicates whether the
    response can be shared with requesting code from the given origin.

    1
    2
    Header type Response       header
    Forbidden header name      no

    A response that tells the browser to allow code from any origin to
    access a resource will include the following:

    1
    Access-Control-Allow-Origin: *

    更多信息,请访问此处….