前端开发中,常常需要进行跨域请求。既然提到跨域,首先我们的知道什么是“同源策略”。
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。
如果协议,端口(如果指定了一个)和域名对于两个页面是相同的,则两个页面具有相同的源。
同一个源内,资源的访问是很自由的。就跟在自己家中,想开冰箱开冰箱,想干啥干啥。如果你想访问不同源的资源,可就没那么自由了,这就是跨域。
关于跨域,常用的JSONP应该都知道。JSONP的原理是什么呢?我们来看看大神贺师俊的解释:
很简单,就是利用<script>标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。 第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。
可以知道JSONP就是个bug般的存在啊,如果你是一个有洁癖的程序员回想说:这不合理,这部干净。因此我们引出cors。
那么,什么是cors呢?
我们来看看互动百科的解释:
CORS(跨来源资源共享)是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是JSONP模式的现代版。
维基百科的解释(手动谷歌):
Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources (e.g. fonts) on a web page to be requested from another domain outside the domain from which the first resource was served.
这样看来,其实嘛,cors就是一个规范,机制,基于这个规范,不同源之间才可以请求资源。相当于一个江湖规矩,大家都按规矩来嘛不是?不讲规矩?信不信小拳拳捶你。
所以呢,要想使用cors跨域访问,你就得讲规矩。下面我们来看看有哪些规矩。
跨域资源共享标准( cross-origin sharing standard )允许在下列场景中使用跨域 HTTP 请求:
- 前文提到的由 XMLHttpRequest 或 Fetch 发起的跨域 HTTP 请求。
- Web 字体 (CSS 中通过 @font-face 使用跨域字体资源), 因此,网站就可以发布
- TrueType 字体资源,并只允许已授权网站进行跨站调用。
- WebGL 贴图
- 使用 drawImage 将 Images/video 画面绘制到 canvas
样式表(使用 CSSOM) - Scripts (未处理的异常)
cors中有个术语叫“简单请求”,若请求满足所有下述条件,则该请求可视为“简单请求”:
使用下列方法之一:
- GET
- HEAD
- POST
//注:仅当POST方法的Content-Type值等于下列之一才算作简单请求
Content-Type :
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
之所以区分简单请求,是因为cors需要处理一些“非简单请求”,这种特殊处理叫做“预检请求”。大人物来了,总要提前准备准备吧,封路啥的blabla。
预检请求的作用是提前获知服务器是否允许该实际请求。“预检请求”的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
一张图可以清晰看到提前发送预检请求的cors请求
可以打开控制台看到我的博客系统中的
getArts
接口的预检请求
Request Headers:
- Accept:/
- Accept-Encoding:gzip, deflate
- Accept-Language:zh-CN,zh;q=0.8,en;q=0.6
- Access-Control-Request-Headers:content-type
- Access-Control-Request-Method:POST
- Host:47.52.5.137:3011
- Origin:http://47.52.5.137:4011
- Proxy-Connection:keep-alive
- Referer:http://47.52.5.137:4011/
- User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Response Header:
- Access-Control-Allow-Headers:content-type
- Access-Control-Allow-Methods:GET,PUT,POST,DELETE,HEAD,OPTIONS
- Access-Control-Allow-Origin:http://47.52.5.137:4011
- Date:Wed, 19 Jul 2017 02:31:10 GMT
- Proxy-Connection:Keep-alive
使用fetch发送cors跨域请求:
return fetch(url, {
method: 'POST',
// 设置这个header,才能正确parse
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
})
.then(response => response.json())
.then(data => {
console.log(data)
dispatch({
type: GET_ARTICLES,
articles: data.articles
})
})
cors在koa中的使用:
import cors from 'koa2-cors'
app.use(cors())
开源个人博客(欢迎star&fork)
github地址:https://github.com/wtfjun/chenxj-blog
在线地址:http://47.52.5.137:4011/
相关链接: