你可能不知道的CORS跨域资源共享_javascript技巧_脚

来源:http://www.chinese-glasses.com 作者:Web前端 人气:123 发布时间:2020-03-14
摘要:时间: 2019-12-02阅读: 83标签:资源知识要点浏览器强制执行同源策略,拒绝不同站点的网站访问。同源策略不会阻止对其他源的请求,但是会禁用对JS 响应的访问。CORS 标头允许访问跨域响

时间: 2019-12-02阅读: 83标签: 资源知识要点浏览器强制执行同源策略,拒绝不同站点的网站访问。同源策略不会阻止对其他源的请求,但是会禁用对 JS 响应的访问。CORS 标头允许访问跨域响应。CORS 与 Credentials 一起时需要谨慎。CORS 是一个浏览器强制策略,其他应用程序不受此影响。事例讲解

什么是CORS?

为了缩小代码量,这里演示部分代码,完全的代码在Github上可以得到。

默认情况下,为预防某些而已行为,浏览器的XHR对象只能访问来源于同一个域中的资源。但是我们在日常实际开发中,常常会遇到跨域请求的需求,因此就出现了一种跨域请求的方案:CORS(Cross-Origin Resource Sharing)跨域资源共享。

咱们从一个例子开始,假设咱们有一个网站,网址为

CORS背后的原理是:使用自定的HTTP头部与服务器进行沟通,从而由服务器决定响应是否成功。

app.get('/public', function(req, res) { res.send(JSON.stringify({ message: 'This is public' }));})

了解下同源策略

咱们还有一个简单的登录功能,用户可以输入一个共享的密匙并设置一个cookie,以将其标识为已验证:

源*:就是协议、域名和端口号; 同源: 就是源相同,即协议、域名和端口完全相同; 同源策略:同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源; 同源策略的分类: DOM 同源策略:即针对于DOM,禁止对不同源页面的DOM进行操作;如不同域名的 iframe 是限制互相访问。 XMLHttpRequest 同源策略:禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。 不受同源策略限制: 页面中的链接,重定向以及表单提交(因为表单提交,数据提交到action域后,本身页面就和其没有关系了,不会管请求结果,后面操作都交给了action里面的域)是不会受到同源策略限制的。 资源的引入不受限制,但是js不能读写加载的内容:如嵌入到页面中的

app.post('/login', function(req, res) { if(req.body.password === 'secret') { req.session.loggedIn = true res.send('You are now logged in!') } else { res.send('Wrong password.') }})

,,,

咱们通过/private获取一些私有数据,就可以通过上面登录状态来做进一步验证。

app.get('/private', function(req, res) { if(req.session.loggedIn === true) { res.send(JSON.stringify({ message: 'THIS IS PRIVATE' })) } else { res.send(JSON.stringify({ message: 'Please login first' })) }})

为什么要跨域限制

通过 AJAX 从其他域请求咱们的 API

如果没有 DOM 同源策略:那么就没有啥xss的研究了,因为你的网站将不是你的网站,而是大家的,谁都可以写个代码操作你的网站界面 如果没有XMLHttpRequest 同源策略,那么就可以很轻易的进行CSRF攻击: 用户登录了自己的网站页面 a.com,cookie中添加了用户标识。 用户浏览了恶意页面 b.com,执行了页面中的恶意 AJAX 请求代码。 b.com 向 a.com发起 AJAX HTTP 请求,请求会默认把 a.com对应cookie也同时发送过去。 a.com从发送的 cookie 中提取用户标识,验证用户无误,response 中返回请求数据;数据就泄露了。而且由于Ajax在后台执行,这一过程用户是无法感知的。 有了XMLHttpRequest 同源策略就可以限制CSRF攻击?别忘了还有不受同源策略的:表单提交和资源引入,

目前,咱们 API 并不是专门设计,但可以允许其他人从/publicURL 中获取数据。 假设咱们的API位于good.com:300/public上,并且咱们的客户端托管在thirdparty.com上,该客户端可能会运行以下代码:

跨域决解方案

fetch('') .then(response = response.text()) .then((result) = { document.body.textContent = result })

JSONP 跨域:借鉴于 script 标签不受浏览器同源策略的影响,允许跨域引用资源;因此可以通过动态创建 script 标签,然后利用 src 属性进行跨域; 缺点: 所有网站都可以拿到数据,存在安全性问题,需要网站双方商议基础token的身份验证。 只能是GET,不能POST。 可能被注入恶意代码,篡改页面内容,可以采用字符串过滤来规避此问题。 服务器代理:浏览器有跨域限制,但是服务器不存在跨域问题,所以可以由服务器请求所要域的资源再返回给客户端。 document.domain、window.name 、location.hash:借助于iframe决解DOM同源策略 postMessage:决解DOM同源策略,新方案 CORS:这里讲的重点

但这在我们的浏览器中不起作用,通过控制的network来看看的请求:

CORS

请求成功,但结果不可用。原因可以在控制台找到:

HTML5 提供的标准跨域解决方案,是一个由浏览器共同遵循的一套控制策略,通过HTTP的Header来进行交互;主要通过后端来设置CORS配置项。

啊哈!咱们缺少Access-Control-Allow-Origin标头。 但是,为什么我们需要它,它有什么用呢?

CORS简单使用

同源策略

之前说得CORS跨域,嗯嗯,后端设置Access-Control-Allow-Origin:*|[或具体的域名]就好了;

我们在 JS 中得不到响应结果的原因是同源策略。该策略的目的是确保一个网站不能读取对另一个网站的请求的结果,并由浏览器强制执行。出于安全方面的考虑,现在的网页都用cookie来进行身份验证,如果不限制读取,网页B里的恶意脚本代码可以随意模仿真实用户进行操作。

app.use => { ctx.set({ "Access-Control-Allow-Origin": "http://localhost:8088"})

例如: 如果在咱们在example.org上,并不会希望该网站向我们的银行网站发出请求,获取咱们的帐户余额和交易。

发现有些请求可以成功,但是有些还是会报错:

同源策略可以防止这种情况的发生。

请求被同源策略阻止,预请求的响应没有通过检查:http返回的不是ok?

在这种情况下,“来源”由

并且发现发送的是OPTIONS请求:

协议(如http)域名(如example.com)端口(如8000)关于CSRF(跨站点请求伪造) 的说明

发现:CORS规范将请求分为两种类型,一种是简单请求,另外一种是带预检的非简单请求

请注意,有一类攻击称为CSRF(跨站点请求伪造),它无法通过同源策略来避免。

简单请求和非简单请求

CSRF攻击中,攻击者向后台的第三方页面发出请求,例如向咱们的银行网站发送POST请求。如果我们与我们的银行存在一个有效的会话,任何网站都可以在后台发出请求,该请求将被执行,除非咱们的银行网站有针对CSRF的反措施。

浏览器发送跨域请求判断方式:

注意,尽管同源策略已经生效,但是的咱们的示例请求从thirdparty.com成功请求到good.com,只是我们无法获得结果。但对于CSRF来说,不需要获取的结果。

浏览器在发送跨域请求的时候,会先判断下是简单请求还是非简单请求,如果是简单请求,就先执行服务端程序,然后浏览器才会判断是否跨域; 而对于非简单请求,浏览器会在发送实际请求之前先发送一个OPTIONS的HTTP请求来判断服务器是否能接受该跨域请求;如果不能接受的话,浏览器会直接阻止接下来实际请求的发生。

例如,有个API通过POST请求方式发送邮件,返回的内容是咱们需要关心的,蛤攻击者不在乎结果,他们关心的是电子邮件是否有发送了成功。

1、请求方法是如下之一:

为咱们的 API 启用 CORS

GET HEAD POST

现在,咱们希望允许第三方站点(如thirdparty.com)上的 JS 访问咱们的 API 能得到响应。为此,我们可以根据错误提示启用CORS标头:

2、所有的Header都只包含如下列表中:

app.get('/public', function(req, res) { res.set('Access-Control-Allow-Origin', '*') res.send(...)})

Cache-Control Content-Language Content-Type Expires Last-Modified Pragma

这里将access-control-allow-origin标头设置为*,这意味着:允许任何主机访问此URL和获取响应的结果:

除此之外都是非简单请求

非简单的请求和预检

CORS非简单请求配置须知

如果请求不是简单请求,浏览器会先发送一个预请求:

正如上图报错显示,对于非简单请求,浏览器会先发送options预检,预检通过后才会发送真是的请求;

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

发送options预检请求将关于接下来的真实请求的信息给服务器:

前面的例子是一个的简单请求。简单的请求是带有一些允许的标头和标志头值的GET或POST请求。现在,对thirdparty.com进行了一些更改让它能获取到JSON格式的数据。

Origin:请求的源域信息Access-Control-Request-Method:接下来的请求类型,如POST、GET等Access-Control-Request-Headers:接下来的请求中包含的用户显式设置的Header列表

fetch('', { headers: { 'Content-Type': 'application/json' }}) .then(response = response.json()) .then((result) = { document.body.textContent = result.message })

服务器端收到请求之后,会根据附带的信息来判断是否允许该跨域请求,通过Header返回信息:

但这又让thirdparty.com崩溃了,network面板向我们展示了原因:

Access-Control-Allow-Origin:允许跨域的Origin列表Access-Control-Allow-Methods:允许跨域的方法列表Access-Control-Allow-Headers:允许跨域的Header列表,防止遗漏Header,因此建议没有特殊需求的情况下设置为*Access-Control-Expose-Headers:允许暴露给JavaScript代码的Header列表Access-Control-Max-Age:最大的浏览器预检请求缓存时间,单位为s

浏览器发现,这是一个非简单请求,就自动发出一个"预检"请求,"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的,头信息里面,关键字段是Origin,表示请求来自哪个源。除了Origin字段,"预检"请求的头信息包括两个特殊字段。

CORS完整配置

本文由10bet发布于Web前端,转载请注明出处:你可能不知道的CORS跨域资源共享_javascript技巧_脚

关键词:

频道精选

最火资讯