跨域资源共享 (CORS) 概念

Posted

技术标签:

【中文标题】跨域资源共享 (CORS) 概念【英文标题】:Cross-origin resource sharing (CORS) concept 【发布时间】:2014-10-08 05:55:03 【问题描述】:

我有一个关于跨域 javascript 概念的问题。

有服务器(例如 amazon.com),只有在选定的域中才能使用其网络服务。 所以肯定的是,如果我尝试从我当地使用他们的服务,我不能。 我在我的控制台上得到了这个

跨域请求被阻止:同源策略不允许读取 远程资源在 http://football20.myfantasyleague.com/2014/export?TYPE=rosters&L=52761&W=&JSON=0。 这可以通过将资源移动到同一域或 启用 CORS。

PS:我也是用jquery跨域的方式,但是没用。

但是,如果选定的域中的某个域使用亚马逊的网络服务,有一个 JavaScript,如果我们将它包含在我们的 html 中,它就可以工作。

<script src="http://example.com"></script>

他们有办法通过 Ajax 获得响应。

我的问题是:

    当我们从 Internet url 引用 JavaScript 文件时会发生什么。我们的机器上是否运行了本地副本? 是否已创建 httpRequest,将有一个请求源作为我的域或 xyz。

【问题讨论】:

ajax 请求的相关域是加载主页面的域。 &lt;script&gt; 标签加载的 JavScript 文件的 URL 没有区别。 是的,当页面从 &lt;script&gt; 标记加载 JavaScript 时,该文件实际上被获取并在客户端中运行。 @Pointy:感谢您的回复,但是请求如何从他的方法中获得响应,当我将相同的构造复制并粘贴到本地时,它不起作用?请解释一下,如果您对跨浏览器有任何参考,不胜感激 如果服务器配置为允许来自某个域的请求,而您的域不是该域,那么它将无法工作。服务器可以配置为允许来自任何域的请求,或来自某些特定域列表的请求。 这是后端的问题吧?这不是 Javascrypt 的问题 【参考方案1】:

这不是前端的问题,这是后端的问题。您应该在后端允许 CORS 来源。

我使用的是 Django。并添加 CORS 中间件并允许 CORS_ORIGINS 解决了这个问题。

添加 CORS 中间件

MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]

并允许 CORS。您可以允许所有来源或仅允许特定来源。

CORS_ORIGIN_ALLOW_ALL = True

只允许特定来源

CORS_ORIGIN_ALLOW_ALL = False

CORS_ORIGIN_WHITELIST = (
    '<YOUR_DOMAIN>[:PORT]',
)

一个例子:

CORS_ORIGIN_ALLOW_ALL = False

CORS_ORIGIN_WHITELIST = (
    '127.0.0.1:3000', 'frontend.com',
)

【讨论】:

【参考方案2】:

在 .htaccess 文件中,只需添加这一行:

Header set Access-Control-Allow-Origin *

【讨论】:

【参考方案3】:

重要提示:如果另一端的服务器未启用它,则您的客户端代码中无能为力跨域ajax请求。

在回答你的问题之前,让我先介绍一下背景:

Same-Origin Security Policy

简单地说,同源安全策略确保来自一个来源的脚本不会从其他来源获取内容。现在给大家解释一下起源的概念,我引用Wikipedia article of Same-Origin Security Policy的部分内容:

下表概述了针对 URL“http://www.example.com/dir/page.html”进行检查的典型结果。

Compared URL                                             Outcome  Reason
-------------------------------------------------------  -------  ----------------------
http://www.example.com/dir/page2.html                    Success  Same protocol and host
http://www.example.com/dir2/other.html                   Success  Same protocol and host
http://username:password@www.example.com/dir2/other.html Success  Same protocol and host
http://www.example.com:81/dir/other.html                 Failure  Same protocol and host but different port
https://www.example.com/dir/other.html                   Failure  Different protocol
http://en.example.com/dir/other.html                     Failure  Different host
http://example.com/dir/other.html                        Failure  Different host (exact match required)
http://v2.www.example.com/dir/other.html                 Failure  Different host (exact match required)
http://www.example.com:80/dir/other.html                 Depends  Port explicit. Depends on implementation in browser.

与其他浏览器不同,Internet Explorer 在计算来源时不包括端口,而是使用安全区域代替它。

因此,例如,您的 JavaScript 无法从(也就是向其发出 HTTP 请求)Web 服务器下载任何东西,而不是它源自的服务器。这正是您不能向其他域发出 XmlHttpRequest(又名 AJAX)的原因。


CORS 是另一端的服务器(不是浏览器中的客户端代码)可以relax the same-origin policy 的一种方式。

关于Cross Origin Resource Sharing (CORS)的过度简化描述。

CORS 标准通过添加新的 HTTP 标头来工作,这些标头允许服务器向允许的源域提供资源。浏览器支持这些标头并遵守它们建立的限制。

示例:假设您的网站是http://my-cool-site.com,并且您在域http://third-party-site.com 上有一个第三方API,您可以通过AJAX 访问它。

让我们假设来自您服务器的页面my-cool-site.comthird-party-site.com 发出了请求。通常,用户浏览器会根据Same-Origin Security Policy 拒绝对您自己的域/子域以外的任何其他站点的 AJAX 调用。但是如果浏览器和第三方服务器支持 CORS,就会发生以下情况:

浏览器将发送和Origin HTTP 标头到third-party-site.com

Origin: http://my-cool-site.com

如果第三方服务器接受来自您的域的请求,它将以Access-Control-Allow-Origin HTTP 标头进行响应:

Access-Control-Allow-Origin: http://my-cool-site.com

要允许所有域,第三方服务器可以发送此标头:

Access-Control-Allow-Origin: *

如果您的网站不被允许,浏览器会报错。

如果客户端的browsers that support CORS 和您的第三方服务器supports CORS 相当现代,CORS 可能对您有用。

在一些过时的浏览器(例如 IE8)中,您必须使用 Microsoft 特定的 XDomainRequest 对象而不是 XMLHttpRequest 来进行与 CORS 一起正常工作的调用;这已经过时了,所有现代浏览器(包括来自微软的)都在 XMLHttpRequest 中处理 CORS。但如果你需要支持过时的浏览器,this page 描述它:

要发出 CORS 请求,您只需在 Firefox 3.5+、Safari 4+ 和 Chrome 中使用 XMLHttpRequest,在 IE8+ 中使用 XDomainRequest 对象。使用XMLHttpRequest 对象时,如果浏览器发现您正在尝试进行跨域请求,它将无缝触发 CORS 行为。

这是一个 javascript 函数,可帮助您创建跨浏览器 CORS 对象。

function createCORSRequest(method, url)
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr)
        // XHR has 'withCredentials' property only if it supports CORS
        xhr.open(method, url, true);
     else if (typeof XDomainRequest != "undefined") // if IE use XDR
        xhr = new XDomainRequest();
        xhr.open(method, url);
     else 
        xhr = null;
    
    return xhr;

同样,这仅适用于过时的浏览器。


以上原因是您无法从脚本中使用亚马逊网络服务的原因。而且亚马逊服务器只允许将他们的 JavaScript 文件下载到从选定域提供的页面。

回答您的编号问题:

    如果文件同源,浏览器将下载该文件。 如果不是同源,CORS 请求成功时会下载该文件。 否则,下载脚本将失败。 如果下载成功,JavaScript 文件的内容将被加载到浏览器的内存中,被解释并执行。

    请参阅 CORS 上的说明以了解。

【讨论】:

【参考方案4】:

CORS 是必须在服务器上修改的设置。它允许外部域请求网页上的资源。简单地更改客户端上的代码不会改变 CORS 的功能。

您可以从“脚本”标签中访问页面的原因是标签的处理方式与跨源请求的所有其他数据不同。在过去,您可以使用将 JSON 数据存储在 HTML 标记内的 JSONP 将 CORS“破解”到您的系统中。

在 Apache 中启用 CORS:

首先通过键入找到您的 httpd.conf

ps -ef | grep apache

这将为您提供 Apache 的位置。找到该类型后:

 <apache-location> -V

这将返回您的 httpd.conf 的确切位置,如下所示:

 -D SERVER_CONFIG_FILE="/etc/apache2/apache2.conf"

现在你需要进入 httpd.conf 并输入“/”来搜索&lt;directory&gt;。找到标签后,立即键入:

Header set Access-Control-Allow-Origin "*"

保存文件并通过运行确认语法正确:

apachectl -t

如果检查成功,请运行正常重启命令:

apachectl -k graceful

一旦服务器重新启动,您的文件现在应该可以通过外部脚本访问了。

如果由于错误而无法保存配置,请尝试退出编辑器并输入:

sudo chmod 755 httpd.conf

这使所有者可以完全访问配置文件,但其他人只能读取和执行它 (http://en.wikipedia.org/wiki/Chmod)。

要测试这些更改,请在外部服务器上创建一个新的 index.html 文件并使用以下内容加载它:

<!doctype html>
<html>
    <head>
    <title>TEST</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.js"></script>
    <script src="http://code.jquery.com/jquery-1.11.1.js"></script>
    <!-- Insert Scripts & CSS Here -->
    <link rel="stylesheet" type="text/css" href="http://d1e24pw9mnwsl8.cloudfront.net/c/bootstrap/css/bootstrap.min.css">
    </head>

    <body>

        <script>
        jQuery.get('yourwebsite.com/file.csv', function(data) 
        document.write(data);
        );
        </script>

    </body>

</html>

生成的输出应反映 yourwebsite.com/file.csv 上的实时数据馈送

如果加载该 html 页面没有显示输出,请在 firefox 上按 f12 打开开发者控制台。您很可能会看到一个错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at yourwebsite.com/file.csv. This can be fixed by moving the resource to the same domain or enabling CORS.

这意味着 a) 您的 httpd.conf 配置不正确/未保存,或者 b) 您忘记重新启动 Web 服务器。

【讨论】:

警告:如果您的服务提供的数据不打算公开,Access-Control-Allow-Origin "*" 可能非常有害。 b> 你是对的。也可以指定具体的url:Access-Control-Allow-Origin: http://www.example-website.com 我认为这对 OP 没有帮助,因为他希望能够在亚马逊的服务器中 sudo chmod 755 httpd.conf

以上是关于跨域资源共享 (CORS) 概念的主要内容,如果未能解决你的问题,请参考以下文章

跨域(CORS)

cors,跨域资源共享,Java配置

CORS跨域资源共享漏洞

WebApi开启CORS支持跨域POST

跨域解决方案 - 跨域资源共享cors

AJAX入门