XMLHttpRequest无法加载XXX没有'Access-Control-Allow-Origin'标头 [英] XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header

查看:195
本文介绍了XMLHttpRequest无法加载XXX没有'Access-Control-Allow-Origin'标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL;博士;关于同源策略



我有一个Grunt进程,它启动了express.js服务器的实例。刚刚开始提供空白页面,并且Chrome中的开发人员控制台中的错误日志中出现以下内容(最新版本),这一直非常正常工作:


XMLHttpRequest无法加载



注意:有些请求很复杂并发送预检 OPTIONS请求服务器必须先响应浏览器将发送GET / POST / PUT /无论JS想要做什么请求。仅将 Access-Control-Allow-Origin 添加到特定URL的CORS实现通常会因此而被绊倒。






显然,通过CORS授予权限是Bob只有在以下情况下才会做的事情:




  • 数据不是私人

  • Mallory值得信赖



如果在这种情况下你也是Bob,那么你添加CORS权限标题的具体细节将取决于你选择的HTTP服务器软件的一些组合以及你用于服务器端编程的语言(如果有的话)。



Mallory 无法添加此标题,因为她必须获得Bob网站的许可,这对于使SOP无用而言是愚蠢的她能够给自己许可。






提及预检回应的错误消息



一些交叉来源请求是预检



这种情况发生在(大致说来)你试图做出一个跨原始请求:




  • 包含Cookie等凭据

  • 无法使用常规HTML表单生成(例如,自定义标题或您无法在表单中使用的内容类型 enctype )。



请注意,自定义标头包含 Access-Control-Allow-Origin 和其他CORS响应头。这些不属于请求,不做任何有用的事情(你可以授予自己权限的权限系统的重点是什么?),并且必须只出现在响应上。



在这些情况下,此答案的其余部分仍然适用,但您还需要确保服务器可以监听预检请求(这将是选项(而不是 GET POST 或您尝试发送的任何内容)和用正确的 Access-Control-Allow-Origin 标题回复它,还要 Access-Control-Allow-Methods Access-Control-Allow-Headers 允许您使用特定的HTTP方法或标题。






CORS的替代方案



JSONP



鲍勃也可以使用类似<的黑客提供数据a href =https://stackoverflow.com/questions/2067472/what-is-jsonp-all-about> JSONP ,这是人们如何跨越Ajax b在CORS出现之前。



它的工作原理是以JavaScript程序的形式呈现数据,将数据注入Mallory的页面。



它要求Mallory信任Bob不提供恶意代码。



注意常见主题:提供数据的网站必须告诉浏览器第三方网站可以访问它发送到浏览器的数据。



将两个资源移动到一个Origin



如果JS运行的HTML文档和URL是请求的是相同的源(共享相同的方案,主机名和端口),然后默认情况下它们同源策略授予权限。不需要CORS。



代理



Mallory 可以使用服务器端用于获取数据的代码(然后她可以像往常一样通过HTTP从她的服务器传递到Alice的浏览器)。



它将:




  • 添加CORS标题

  • 将响应转换为JSONP

  • 存在于同一来源上HTML文档



服务器端代码可以由第三方托管(例如YQL)。



Bob不需要授予任何权限。



这很好,因为那只是在Mallory和Bob之间。 Bob没有办法认为Mallory是Alice并且为Mallory提供了应该在Alice和Bob之间保密的数据。



因此,Mallory只能使用这个读取公共数据的技术。



写一些非Web应用程序



如同为何同源原则政策仅适用一节所述对于网页中的JavaScript,您可以通过不在网页中编写JavaScript来避免使用SOP。



这并不意味着您无法继续使用JavaScript和HTML,但您可以使用其他机制(例如Node-WebKit或PhoneGap)来分发它。 / p>

浏览器扩展



浏览器扩展可能会在同一起源之前的响应中注入CORS头政策适用。



这些对于开发很有用,但对于生产站点不实用(要求站点的每个用户安装禁用其浏览器安全功能的浏览器扩展是不合理的)。



它们也只适用于简单的请求(处理预检OPTIONS请求时失败)。



拥有适当的开发环境与本地开发服务器
通常是一种更好的方法。






其他安全风险



注意SOP / CORS做没有减轻 XSS CSRF ,或 SQL Injection 需要独立处理的攻击。






摘要




  • 那里您无法在您的客户端代码中执行任何操作,该代码将启用对某人其他人的服务器的CORS访问。

  • 如果您控制服务器正在执行以下操作:为其添加CORS权限。

  • 如果您对控制它的人很友好:让他们为其添加CORS权限。

  • 如果是公共服务:请阅读他们的API文档,了解他们对使用客户端JavaScript访问它的看法。他们可能会告诉您使用特定的URL或使用JSONP(或者他们可能根本不支持它)。

  • 如果以上都不适用:让浏览器与交谈您的服务器,然后让您的服务器从其他服务器获取数据并将其传递。 (还有第三方托管服务将CORS标头附加到您可以使用的公共可访问资源)。


tl;dr; About the Same Origin Policy

I have a Grunt process which initiates an instance of express.js server. This was working absolutely fine up until just now when it started serving a blank page with the following appearing in the error log in the developer's console in Chrome (latest version):

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.

What is stopping me from accessing the page?

解决方案

About the Same Origin Policy

This is the Same Origin Policy. It is a security feature implemented by browsers.

Your particular case is showing how it is implemented for XMLHttpRequest (and you'll get identical results if you were to use fetch), but it also applies to other things (such as images loaded onto a <canvas> or documents loaded into an <iframe>), just with slightly different implementations.

(Weirdly, it also applies to CSS fonts, but that is because found foundries insisted on DRM and not for the security issues that the Same Origin Policy usually covers).

The standard scenario that demonstrates the need for the SOP can be demonstrated with three characters:

  • Alice is a person with a web browser
  • Bob runs a website (https://www.[website].com/ in your example)
  • Mallory runs a website (http://localhost:4300 in your example)

Alice is logged into Bob's site and has some confidential data there. Perhaps it is a company intranet (accessible only to browsers on the LAN), or her online banking (accessible only with a cookie you get after entering a username and password).

Alice visits Mallory's website which has some JavaScript that causes Alice's browser to make an HTTP request to Bob's website (from her IP address with her cookies, etc). This could be as simple as using XMLHttpRequest and reading the responseText.

The browser's Same Origin Policy prevents that JavaScript from reading the data returned by Bob's website (which Bob and Alice don't want Mallory to access). (Note that you can, for example, display an image using an <img> element across origins because the content of the image is not exposed to JavaScript (or Mallory) … unless you throw canvas into the mix in which case you will generate a same-origin violation error).


Why the Same Origin Policy applies when you don't think it should

For any given URL it is possible that the SOP is not needed. A couple of common scenarios where this is the case are:

  • Alice, Bob and Mallory are the same person.
  • Bob is providing entirely public information

… but the browser has no way of knowing if either of the above are true, so trust is not automatic and the SOP is applied. Permission has to be granted explicitly before the browser will give the data it was given to a different website.


Why the Same Origin Policy only applies to JavaScript in a web page

Browser extensions, the Network tab in browser developer tools and applications like Postman are installed software. They aren't passing data from one website to the JavaScript belonging to a different website just because you visited that different website. Installing software usually takes a more conscious choice.

There isn't a third party (Mallory) who is considered a risk.


Why you can display data in the page without reading it with JS

There are a number of circumstances where Mallory's site can cause a browser to fetch data from a third party and display it (e.g. by adding an <img> element to display an image). It isn't possible for Mallory's JavaScript to read the data in that resource though, only Alice's browser and Bob's server can do that, so it is still secure.


CORS

The Access-Control-Allow-Origin header referred to in the error message is part of the CORS standard which allows Bob to explicitly grant permission to Mallory's site to access the data via Alice's browser.

A basic implementation would just include:

Access-Control-Allow-Origin: *

… to permit any website to read the data.

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

… would allow only a specific site to access it, and you can dynamically generate that based on the Origin request header to permit multiple, but not all, sites to access it.

The specifics of how you set that response header depend on Bob's HTTP server and/or server-side programming language. There is a collection of guides for various common configurations that might help.

NB: Some requests are complex and send a preflight OPTIONS request that the server will have to respond to before the browser will send the GET/POST/PUT/Whatever request that the JS wants to make. Implementations of CORS that only add Access-Control-Allow-Origin to specific URLs often get tripped up by this.


Obviously granting permission via CORS is something Bob would only do only if either:

  • The data was not private or
  • Mallory was trusted

If you are also Bob in this scenario, then the specifics of how you add CORS permission headers will depend on some combination of your choice of HTTP server software and what language you are using for server-side programming (if any).

Mallory can't add this header because she has to get permission from Bob's site and it would be silly (to the point of rendering the SOP useless) for her to be able to grant herself permission.


Error messages which mention "Response for preflight"

Some cross origin requests are preflighted.

This happens when (roughly speaking) you try to make a cross-origin request that:

  • Includes credentials like cookies
  • Couldn't be generated with a regular HTML form (e.g. has custom headers or a Content-Type that you couldn't use in a form's enctype).

Note that "custom headers" include Access-Control-Allow-Origin and other CORS response headers. These don't belong on the request, don't do anything helpful (what would be the point of a permissions system where you could grant yourself permission?), and must appear only on the response.

In these cases then the rest of this answer still applies but you also need to make sure that the server can listen for the preflight request (which will be OPTIONS (and not GET, POST or whatever you were trying to send) and respond to it with the right Access-Control-Allow-Origin header but also Access-Control-Allow-Methods and Access-Control-Allow-Headers to allow your specific HTTP methods or headers.


Alternatives to CORS

JSONP

Bob could also provide the data using a hack like JSONP which is how people did cross-origin Ajax before CORS came along.

It works by presenting the data in the form of a JavaScript program which injects the data into Mallory's page.

It requires that Mallory trust Bob not to provide malicious code.

Note the common theme: The site providing the data has to tell the browser that it is OK for a third party site to access the data it is sending to the browser.

Move the two resources to a single Origin

If the HTML document the JS runs in and the URL being requested are on the same origin (sharing the same scheme, hostname, and port) then they Same Origin Policy grants permission by default. CORS is not needed.

A Proxy

Mallory could use server-side code to fetch the data (which she could then pass from her server to Alice's browser through HTTP as usual).

It will either:

  • add CORS headers
  • convert the response to JSONP
  • exist on the same origin as the HTML document

That server-side code could be hosted by a third party (such as YQL).

Bob wouldn't need to grant any permissions for that to happen.

This would be fine since that is just between Mallory and Bob. There is no way for Bob to think that Mallory is Alice and to provide Mallory with data that should be kept confidential between Alice and Bob.

Consequently, Mallory can only use this technique to read public data.

Writing something other than a web app

As noted in the section "Why the Same Origin Policy only applies to JavaScript in a web page", you can avoid the SOP by not writing JavaScript in a webpage.

That doesn't mean you can't continue to use JavaScript and HTML, but you could distribute it using some other mechanism, such as Node-WebKit or PhoneGap.

Browser extensions

It is possible for a browser extension to inject the CORS headers in the response before the Same Origin Policy is applied.

These can be useful for development, but are not practical for a production site (asking every user of your site to install a browser extension that disables a security feature of their browser is unreasonable).

They also tend to work only with simple requests (failing when handling preflight OPTIONS requests).

Having a proper development environment with a local development server is usually a better approach.


Other security risks

Note that SOP / CORS do not mitigate XSS, CSRF, or SQL Injection attacks which need to be handled independently.


Summary

  • There is nothing you can do in your client-side code that will enable CORS access to someone else's server.
  • If you control the server the request is being made to: Add CORS permissions to it.
  • If you are friendly with the person who controls it: Get them to add CORS permissions to it.
  • If it is a public service: Read their API documentation to see what they say about accessing it with client-side JavaScript. They might tell you to use specific URLs or to use JSONP (or they might not support it at all).
  • If none of the above apply: Get the browser to talk to your server instead, and then have your server fetch the data from the other server and pass it on. (There are also third-party hosted services which attach CORS headers to publically accessible resources that you could use).

这篇关于XMLHttpRequest无法加载XXX没有'Access-Control-Allow-Origin'标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆