XMLHttpRequest无法加载https:// www。[website] .com / [英] XMLHttpRequest cannot load https://www.[website].com/

查看:260
本文介绍了XMLHttpRequest无法加载https:// www。[website] .com /的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


XMLHttpRequest无法加载 https:// www。[website] .com /
否请求的
资源上存在Access-Control-Allow-Origin头。因此,原产地 http:// localhost:4300 '不允许访问。


什么是阻止我访问该页面?

解决方案

关于同源政策



这是 Same原产地政策。这是一个由浏览器实现的安全功能。



您的具体案例显示了如何为XMLHttpRequest实现(如果要使用fetch,您将获得相同的结果) ,但它也适用于其他东西(例如加载到< canvas> 或加载到< iframe> ),只是稍微不同的实现。



可以使用三个字符




  • 爱丽丝是一个拥有网络浏览器的人

  • <在Bob的例子中,Bob运行一个网站( https:// www。[website] .com /
  • 您的示例中的网站( http:// localhost:4300



爱丽丝已登录到Bob的站点,并在那里提供一些机密数据。也许这是一个公司内部网(只能访问LAN上的浏览器)或网上银行(只有在输入用户名和密码后才能访问您的Cookie)。



Alice访问Mallory的网站,其中有一些JavaScript会导致Alice的浏览器向Bob的网站发出HTTP请求(从她的IP地址与她的cookies等)。这可以像使用 XMLHttpRequest 并阅读 responseText 一样简单。



浏览器的同源策略阻止JavaScript读取Bob网站返回的数据(Bob和Alice不希望Mallory访问)。 (请注意,例如,您可以使用< img> 元素在原始图像之间显示图像,因为图像的内容不会暴露于JavaScript ...除非您抛出画布在这种情况下,您将产生相同的原始违规错误)。






为什么当您不认为应该



对于任何给定的URL,可能不需要SOP,则适用同源策略。在这种情况下,一些常见的情况是:




  • 爱丽丝,鲍勃和马洛里是同一个人。

  • Bob正在提供完全公开的信息



...但浏览器无法知道是否以上任何一种都是真实的,所以信任不是自动的,而是应用SOP。必须明确授予权限,然后浏览器才能将数据提供给不同的网站。






为什么是同一个起始策略仅适用于网页中的JavaScript



浏览器扩展,浏览器开发人员工具和Postman中的应用程序中的网络选项卡已安装软件。由于您访问了不同的网站,因此他们不会将数据从一个网站传递到属于其他网站的JavaScript。安装软件通常需要更有意识的选择。



没有第三方(马洛里)被认为是风险。






为什么您可以在页面中显示数据而不用JS阅读?



有一些情况马洛里的网站可以使浏览器从第三方获取数据并显示(例如,添加< img> 元素以显示图像)。马洛里的JavaScript不可能读取该资源中的数据,只有Alice的浏览器和Bob的服务器可以这样做,所以它仍然是安全的。






CORS



Access-Control-Allow-Origin 错误消息是 CORS 标准的一部分,允许Bob明确授权Mallory的网站通过Alice的浏览器访问数据。



基本实现只包括:

  Access-Control-允许原产地:* 

...允许任何网站读取数据。

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

...只允许特定的网站访问它,您可以根据 Origin 请求标头以允许多个但不是全部的站点访问它。



您如何设置响应标头的具体细节取决于Bob的HTTP服务器和/或服务器端编程语言。 有关各种常见配置的指南可能有帮助。



注意:有些请求很复杂,并发送一个 preflight OPTIONS请求服务器将必须响应之前,浏览器将发送GET / POST / PUT /任何请求,JS想要做的。




>

显然,通过CORS授予权限是Bob只会在以下情况下执行:




  • 数据不是私人的

  • 马洛里被信任



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



马洛里不能添加此标题,因为她必须获得Bob网站的许可,并且对于她来说,这将是愚蠢的(为了使SOP无效)能够授予自己的许可。






提到预检反应的错误消息



一些跨源请求是预检



发生这种情况(粗略地说)你试图做出一个十字架请求:




  • 包含Cookie等凭据

  • 无法使用常规HTML表单生成(例如,您可以在表单的<$中使用自定义标题或Content-Type c $ c> enctype )。



在这些情况下,这个答案的其余部分仍然应用,但您还需要确保服务器可以侦听预检请求(这将是 OPTIONS (而不是 GET POST 或您尝试发送的任何内容),并使用正确的 Access-Control-Allow-Origin 头,还可以访问控制允许方法访问控制允许头允许您的特定HTTP方法或标头。






CORS的替代方案



JSONP



Bob还可以提供数据usi像 JSONP 这样的黑客攻击,这是CORS来来之前人们如何跨越Ajax



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



它要求Mallory信任Bob不提供恶意代码。注意共同的主题:提供数据的网站必须告诉浏览器,第三方网站可以访问发送到浏览器的数据。



将两个资源移动到单个Origin



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



代理



马洛里可以使用服务器端代码获取数据(然后她可以照常通过HTTP从服务器传递到Alice的浏览器)。



它将:




  • 添加CORS标头

  • 将响应转换为JSONP

  • 存在于与HTML文档



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



Bob不需要授予任何权限来实现。



这是很好的,因为这只是在马洛里和鲍勃之间。 Bob没有办法认为Mallory是爱丽丝,并为Mallory提供了Alice和Bob之间应保密的数据。



因此,Mallory只能使用公开数据的技术。



写入除webapp之外的其他东西



如同原产地规则仅适用于网页中的JavaScript,您可以通过在网页中编写JavaScript来避免SOP。



这并不意味着您不能继续使用JavaScript和HTML,但您可以使用其他一些机制(如Node-WebKit或PhoneGap)进行分发。 / p>




其他安全风险



请注意,SOP / CORS不减轻 XSS CSRF SQL Injection 攻击需要独立处理。






摘要




  • 您可以在您的客户端代码中执行任何操作,这将允许CORS访问某人 服务器。

  • 如果您控制服务器请求的方式是:向其添加CORS权限。

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

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

  • 如果上述都不适用:让浏览器与您的服务器,然后让您的服务器从其他服务器提取数据并将其传递。


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.[website].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.

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 … 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).

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 webapp

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.


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.

这篇关于XMLHttpRequest无法加载https:// www。[website] .com /的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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