XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
我有一个grunt进程来启动express.js服务器的实例。直到现在,它才开始提供一个空白页面,在开发人员的控制台中的错误日志中显示了以下内容(最新版本):
XMLHttpRequest cannot load https://www.example.com/
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4300' is therefore not allowed access.
是什么阻止我访问页面?
关于同一原产地政策
这是同一原产地政策。它是由浏览器实现的安全功能。好的。
您的特定案例展示了它是如何为xmlhttprequest实现的(如果使用fetch,您将得到相同的结果),但它也适用于其他事情(例如加载到
(奇怪的是,它也适用于CSS字体,但这是因为found foundries坚持使用DRM,而不是同一源站策略通常涉及的安全问题)。好的。
演示SOP需求的标准方案可以用三个字符来演示:好的。
- 爱丽丝是个有网络浏览器的人
- Bob运行一个网站(在您的示例中是
https://www.[website].com/ ) - Mallory运行一个网站(在您的示例中是
http://localhost:4300 )
爱丽丝登录了鲍勃的网站,那里有一些机密数据。可能是公司内部网(只能访问局域网上的浏览器)或她的网上银行业务(只能通过输入用户名和密码后获得的cookie访问)。好的。
Alice访问Mallory的网站,该网站有一些JavaScript,使Alice的浏览器向Bob的网站发出HTTP请求(通过其IP地址和cookies等)。这可能和使用
浏览器的同一源代码策略阻止javascript读取Bob的网站返回的数据(Bob和Alice不希望Mallory访问)。(请注意,您可以使用
对于任何给定的URL,可能不需要SOP。一些常见的情况是:好的。
- 爱丽丝、鲍勃和马洛里是同一个人。
- 鲍勃提供完全公开的信息
…但是浏览器无法知道上面的任何一个是否正确,因此信任不是自动的,并且应用了SOP。在浏览器将数据提供给其他网站之前,必须明确授予权限。好的。为什么同一源策略只适用于网页中的javascript?
浏览器扩展、浏览器开发人员工具和应用程序(如邮差)中的"网络"选项卡是已安装的软件。他们不会将数据从一个网站传递到属于不同网站的javascript,只是因为您访问了不同的网站。安装软件通常需要更明智的选择。好的。
没有第三方(Mallory)被视为风险。好的。为什么不用JS就可以在页面中显示数据?
在许多情况下,Mallory的站点会导致浏览器从第三方获取数据并显示它(例如,通过添加
错误消息中引用的
一个基本的实现只包括:好的。
1 | Access-Control-Allow-Origin: * |
…允许任何网站读取数据。好的。
1 | Access-Control-Allow-Origin: http://example.com/ |
…将只允许特定站点访问它,并且您可以基于
如何设置响应头的细节取决于Bob的HTTP服务器和/或服务器端编程语言。对于各种常见配置,有一组指南可能会有所帮助。好的。
好的。
注意:有些请求很复杂,在浏览器发送JS想要发出的get/post/put/任何请求之前,服务器必须响应一个飞行前选项请求。只向特定URL添加
显然,通过CORS授予许可是Bob唯一能做的事情,只有在以下两种情况下:好的。
- 数据不是私有的或
- 马洛里值得信任
如果您也是这个场景中的Bob,那么如何添加CORS权限头的具体情况将取决于您选择的HTTP服务器软件和用于服务器端编程的语言(如果有的话)的某种组合。好的。
Mallory无法添加此标题,因为她必须获得Bob网站的许可,如果她能够授予自己许可,那将是愚蠢的(到使SOP无用的程度)。好的。提示"飞行前响应"的错误消息
一些跨源请求是预先设定的。好的。
当(粗略地说)您试图提出跨源请求时,会发生这种情况:好的。
- 包括凭证,如cookie
- 无法使用常规HTML表单生成(例如,具有自定义头或无法在表单的
enctype 中使用的内容类型)。
注意,"自定义头"包括
在这些情况下,此答案的其余部分仍然适用,但您还需要确保服务器能够侦听飞行前请求(它将是
Bob还可以使用类似于JSONP的黑客提供数据,这就是人们在CORS出现之前如何跨源代码Ajax。好的。
它的工作原理是以javascript程序的形式呈现数据,将数据注入Mallory的页面。好的。
它要求Mallory信任Bob不提供恶意代码。好的。
注意共同的主题:提供数据的站点必须告诉浏览器第三方站点可以访问它发送给浏览器的数据。好的。
由于jsonp的工作方式是附加一个
如果JS运行的HTML文档和被请求的URL位于同一个源站(共享相同的方案、主机名和端口),那么它们默认为同一源站策略授予权限。不需要CORS。好的。代理人
Mallory可以使用服务器端代码来获取数据(然后她可以像往常一样通过HTTP将数据从服务器传递到Alice的浏览器)。好的。
它也可以:好的。
- 添加CORS标题
- 将响应转换为JSONP
- 与HTML文档在同一源文件上存在
该服务器端代码可以由第三方(如YQL)托管。好的。
Bob不需要为实现这一点授予任何权限。好的。
这很好,因为那只是马洛里和鲍勃之间的事。Bob无法认为Mallory是Alice,也无法向Mallory提供Alice和Bob之间应保密的数据。好的。
因此,Mallory只能使用此技术读取公共数据。好的。编写Web应用以外的内容
如"为什么同一源代码策略只适用于网页中的javascript"一节所述,您可以通过不在网页中编写javascript来避免SOP。好的。
这并不意味着您不能继续使用JavaScript和HTML,但您可以使用其他机制(如node webkit或phonegap)来分发它。好的。浏览器扩展
浏览器扩展可以在应用同一源策略之前将CORS头插入响应中。好的。
这些功能对于开发很有用,但对于生产站点来说并不实际(要求站点的每个用户安装一个禁用浏览器安全功能的浏览器扩展是不合理的)。好的。
它们也倾向于只处理简单的请求(在处理飞行前选项请求时失败)。好的。
与本地开发服务器具有适当的开发环境通常是更好的方法。好的。其他安全风险
请注意,SOP/CORS不能缓解需要独立处理的XSS、CSRF或SQL注入攻击。好的。总结
- 在您的客户端代码中,没有什么可以使CORS能够访问其他人的服务器。
- 如果控制服务器,则请求将被发送到:向其添加CORS权限。
- 如果你对控制它的人很友好:让他们向它添加CORS权限。
- 如果是公共服务:请阅读他们的API文档,了解他们对使用客户端JavaScript访问它的看法。他们可能会告诉您使用特定的URL或使用JSONP(或者根本不支持)。
- 如果以上都不适用:让浏览器与您的服务器对话,然后让您的服务器从另一个服务器获取数据并传递。(还有第三方托管服务,它们将CORS头附加到您可以使用的公共可访问资源上)。
好啊。
目标服务器必须允许跨源请求。为了允许它通过Express,只需处理HTTP选项请求:
1 2 3 4 5 6 7 | app.options('/url...', function(req, res, next){ res.header('Access-Control-Allow-Origin',"*"); res.header('Access-Control-Allow-Methods', 'POST'); res.header("Access-Control-Allow-Headers","accept, content-type"); res.header("Access-Control-Max-Age","1728000"); return res.sendStatus(200); }); |
因为在接受的答案中没有提到这一点。
- 对于这个确切的问题,情况并非如此,但可能有助于其他搜索该问题的人。
- 在某些情况下,您可以在客户机代码中这样做来防止CORS错误。
您可以利用简单的请求。为了执行"简单请求",请求需要满足几个条件。例如,只允许使用
如果您的客户机代码没有显式地在请求中使用固定值设置受影响的头(例如"accept"),那么可能会出现一些客户机使用一些"非标准"值自动设置这些头,导致服务器不将其作为简单请求接受-这将给您一个CORS错误。
这是因为CORS错误。CORS代表跨源资源共享。简单来说,当我们试图从另一个域访问域/资源时,就会发生此错误。
在这里阅读更多信息:jquery的CORS错误
要解决此问题,如果您有权访问其他域,则必须允许服务器中的访问控制允许源站。这可以添加到标题中。您可以为所有请求/域或特定域启用此功能。
如何使跨源资源共享(CORS)后请求工作
这些链接可能有帮助
这个CORS问题没有进一步阐述(其他原因)。
我现在遇到这个问题的原因不同。我的前端也返回"访问控制允许来源"头错误。
只是我指出了错误的URL,所以这个标题没有正确反映(我一直认为是这样)。localhost(前端)->调用非安全HTTP(假定为HTTPS),确保前端的API端点指向正确的协议。
你应该让CORS工作。