Javascript 访问控制如何允许源标题工作?

Javascript 访问控制如何允许源标题工作?,javascript,cross-domain,cors,Javascript,Cross Domain,Cors,显然,我完全误解了它的语义。我想到了这样的事情: 客户端从http://siteA-原点 MyCode.js的响应头包含访问控制允许来源:http://siteB,我认为这意味着MyCode.js可以对站点B进行跨源引用 客户端触发MyCode.js的一些功能,这些功能反过来向http://siteB,这应该没问题,尽管是跨来源请求 嗯,我错了。它根本不是这样工作的。所以,我已经阅读并试图阅读 有一件事是肯定的-我仍然不明白我应该如何使用这个标题 我对站点A和站点B都有完全的控制权。如何使从站点

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

  • 客户端从
    http://siteA
    -原点
  • MyCode.js的响应头包含访问控制允许来源:
    http://siteB
    ,我认为这意味着MyCode.js可以对站点B进行跨源引用
  • 客户端触发MyCode.js的一些功能,这些功能反过来向
    http://siteB
    ,这应该没问题,尽管是跨来源请求
  • 嗯,我错了。它根本不是这样工作的。所以,我已经阅读并试图阅读

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

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

    附言


    我不想使用JSONP。

    访问控制允许源站
    是一个

    当站点A尝试从站点B获取内容时,站点B可以发送一个
    访问控制允许源站
    响应标题,告诉浏览器某些源站可以访问此页面的内容。(原点为a。)默认情况下,站点B的页面为;使用
    Access Control Allow Origin
    标题打开一扇门,通过特定的请求来源进行跨来源访问

    对于站点B希望站点A访问的每个资源/页面,站点B应为其页面提供响应标题:

    Access-Control-Allow-Origin: http://siteA.com
    
    现代浏览器不会完全阻止跨域请求。如果站点A从站点B请求页面,浏览器将实际在网络级别获取请求的页面,并检查响应头是否将站点A列为允许的请求者域。如果站点B未指示允许站点A访问此页面,浏览器将触发
    XMLHttpRequest
    错误事件,并拒绝请求JavaScript代码的响应数据

    非简单请求 在网络层面上发生的事情可能比上面解释的稍微复杂一些。如果请求是,浏览器首先发送一个无数据的“飞行前”选项请求,以验证服务器是否会接受该请求。在以下情况下,请求是非简单的:

    • 使用非GET或POST的HTTP动词(例如PUT、DELETE)
    • 使用非简单请求头;唯一的简单请求标头是:
      • 接受
      • 接受语言
      • 内容语言
      • 内容类型
        (只有当其值为
        应用程序/x-www-form-urlencoded
        多部分/表单数据
        、或
        文本/普通
        时,这才简单)
    如果服务器使用与非简单谓词和/或非简单标头匹配的适当响应标头(
    Access Control Allow headers
    用于非简单标头,
    Access Control Allow Methods
    用于非简单谓词)响应选项飞行前,则浏览器发送实际请求

    假设站点A想要发送对
    /somePage
    的PUT请求,且非简单
    内容类型
    值为
    application/json
    ,浏览器将首先发送飞行前请求:

    OPTIONS /somePage HTTP/1.1
    Origin: http://siteA.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: Content-Type
    
    请注意,
    访问控制请求方法
    访问控制请求头
    由浏览器自动添加;您不需要添加它们。此选项预飞行获取成功响应标题:

    Access-Control-Allow-Origin: http://siteA.com
    Access-Control-Allow-Methods: GET, POST, PUT
    Access-Control-Allow-Headers: Content-Type
    
    发送实际请求时(飞行前完成后),行为与处理简单请求的方式相同。换句话说,预飞成功的非简单请求被视为与简单请求相同(即,服务器必须再次发送
    Access Control Allow Origin
    ,以获得实际响应)

    浏览器发送实际请求:

    PUT /somePage HTTP/1.1
    Origin: http://siteA.com
    Content-Type: application/json
    
    { "myRequestContent": "JSON is so great" }
    
    服务器会发回一个
    访问控制允许源站
    ,就像对一个简单请求一样:

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

    有关非简单请求的更多信息,请参阅。

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

  • 使用Flash/Silverlight或服务器端作为“代理”进行通信 用遥控器
  • 带填充()的JSON
  • 将远程服务器嵌入iframe中,并通过片段或窗口进行通信。名称,请参阅
  • 这些棘手的方法或多或少都有一些问题,例如,如果开发人员简单地“评估”JSONP,JSONP可能会导致安全漏洞,以及上面的第3条,尽管它可以工作,但两个域应该在彼此之间建立严格的契约,这既不灵活也不优雅(IMHO:)

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

    机制

    从较高的层次上,我们可以简单地认为CORS是来自域a的客户端AJAX调用与域B上托管的页面之间的契约,典型的跨源请求/响应是:

    域AJAX请求头

    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 
    
    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
    
    域B响应头

    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 
    
    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
    
    我上面标记的蓝色部分是核心事实,“来源”请求头“表示跨来源请求或飞行前请求的来源”,“访问控制允许来源”响应头表示此页面允许来自DomainA的远程请求(如果值为*表示允许来自
    header("Access-Control-Allow-Origin: *");
    
    header("Access-Control-Allow-Origin: http://www.website.com");
    
    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();
     });  
    
    res.header("Access-Control-Allow-Headers","*");
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    
    $http({
         method: 'POST',
         url: 'url, 
         withCredentials: true,
         data : {}
       }).then(function(response){
            // code  
       }, function (response) {
             // code 
       });
    
    open -a Google\ Chrome --args --disable-web-security --user-data-dir
    
    axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
          .then(response => console.log(response:data);
      }
    
    $ pip install -U flask-cors
    
    from flask import Flask
    from flask_cors import CORS
    
    app = Flask(__name__)
    CORS(app)
    
    @app.route("/")
    def helloWorld():
      return "Hello, cross-origin-world!"
    
        <httpProtocol>  
        <customHeaders>  
         <add name="Access-Control-Allow-Origin" value="*" />  
         <add name="Access-Control-Allow-Headers" value="Content-Type" />  
         <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />  
        </customHeaders>  
      </httpProtocol>  
    
    Header type Response       header
    Forbidden header name      no
    
    Access-Control-Allow-Origin: *