常用跨域方法总结(2)——CORS

上篇文章介绍了几种常用的跨域方法:常用跨域方法总结,本片为上一篇的补充,对比较重要的Cross Origin Resource Sharing详细介绍。

CORS

出于安全原因,从脚本内发起的跨源HTTP请求会受到一定限制。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非使用CORS头文件。

跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

若要利用CORS来进行跨域获取资源,还需要服务端的配合。
这里分为两种场景:简单请求和非简单请求

简单请求

什么样的请求才属于简单请求呢,让我们先来看MDN的一段定义

  • 必须使用下列方法中的一种:

    • GET
    • HEAD
    • POST
  • 请求首部字段不能超出以下几种

    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (需要注意额外的限制)
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
  • Content-Type 的值仅限于下列三者之一:

    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
  • 请求中没有使用 ReadableStream 对象。

同时满足以上5种条件,则可以视为简单请求。
先跑例子吧。
首先上服务端代码:

var http = require('http');
http.createServer(function (req, res) {
res.setHeader("Access-Control-Allow-Origin","*");
res.end(JSON.stringify({'success':true,msg:'今天,我就是要用cors来跨域'+Math.random()}));
}).listen(8080)

很简单有没有,
Access-Control-Allow-Origin:限制发起跨域请求的来源,*表示不限制
请求首部字段下文详细介绍
前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var xhr = new XMLHttpRequest()
xhr.open('get', 'http://localhost:8080')
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(JSON.parse(xhr.responseText))
}
}
xhr.send()
</script>
</body>
</html>

结果肯定是请求成功啦

非简单请求

简单来说吧,不符合简单请求的都是非简单请求(怎么感觉这么大白话呢- -)详见CORS

与前述简单请求不同,“非简单请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

还是先上代码
服务端:

var http = require('http');
http.createServer(function (req, res) {
res.setHeader("Access-Control-Allow-Origin","*");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
res.setHeader("Access-Control-Allow-Methods","PUT,GET,POST,DELETE,OPTIONS");
res.end(JSON.stringify({'success':true,msg:'今天,我就是要用cors来跨域'+Math.random()}));
}).listen(8080)
console.log('正在监听8080')

Access-Control-Allow-Headers::预检请求响应的首部字段定义了实际请求中允许携带的额外的首部字段。
Access-Control-Allow-Methods:预检请求响应的首部字段定义了实际请求所允许使用的 HTTP 方法。(笔者做实验的遇到了一个小插曲,simple method会不受此限制,详见为什么 Access-Control-Allow-Methods 不起作用?
前端

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var xhr = new XMLHttpRequest()
xhr.open('get', 'http://localhost:8080')
xhr.setRequestHeader('Content-type','text/html') // 添加了非简单请求的Content-Type
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(JSON.parse(xhr.responseText))
}
}
xhr.send()
</script>
</body>
</html>

结果肯定也是请求成功啦。

附带身份凭证的请求

这里有一点要注意的地方,这里还是说一下吧

一般而言,对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位。

也就是前端请求的时候:xhr.withCredentials = true

对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“”。若请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“”,请求将会失败。

请求与响应首部字段总结

这块内容MDN已经很详细了,为了方便阅读,笔者还是整理过来了。

HTTP 请求首部字段

请注意,这些首部字段无须手动设置。 当开发者使用 XMLHttpRequest 对象发起跨域请求时,它们已经被设置就绪。
Origin首部字段表明预检请求或实际请求的源站。(注意,不管是否为跨域请求,ORIGIN 字段总是被发送。)
Access-Control-Request-Method,用于预检请求,表示实际请求的方法
Access-Control-Request-Headers,用于预检请求,表示实际请求中添加的额外的首部字段

HTTP 请求响应字段

Access-Control-Allow-Method,预检请求的响应,表示允许的接下来的实际请求的方法。(笔者做实验的遇到了一个小插曲,simple method会不受此限制,详见为什么 Access-Control-Allow-Methods 不起作用?
Access-Control-Allow-Origin,指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。
Access-Control-Allow-Credentials,当浏览器(比如xhr)的credentials设置为true时是否允许浏览器读取response的内容。当用在对preflight预检测请求的响应中时,它指定了实际的请求是否可以使用credentials(如果请求credentials为true时,该响应首部字段需要设置为true)。
Access-Control-Allow-Headers,预检请求的响应,表示允许的接下来的实际请求的额外的首部字段。预检请求的响应。其指明了实际请求中允许携带的首部字段。
Access-Control-Expose-Headers,在跨域访问时,XMLHttpRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头。
Access-Control-Max-Age:指定了预检请求的结果能够被缓存多久

最后

到这里笔者对跨域算是比较熟悉了,感谢各位的阅读,如有不对的地方,欢迎大家批评指正。
还有,最好是对每个例子都有实际运行理解更深刻哦。

Reference

HTTP访问控制(CORS)

常用跨域方法总结(2)——CORS的更多相关文章

  1. 循序渐进Python3(十一) --6--  Ajax 实现跨域请求 jsonp 和 cors

    Ajax操作如何实现跨域请求?       Ajax (XMLHttpRequest)请求受到同源策略的限制.       Ajax通过XMLHttpRequest能够与远程的服务器进行信息交互,另外 ...

  2. 前端Js跨域方法汇总—剪不断,理还乱,是跨域

    1.通过jsonp跨域2.通过修改document.domain来跨子域(iframe)3.隐藏的iframe+window.name跨域4.iframe+跨文档消息传递(XDM)5.跨域资源共享 C ...

  3. 面试整理(2)跨域:jsonp与CORS

    问题:跨域有哪些方法?jsonp的原理是什么? jsonp: 先说jsonp,jsonp的主要原理是利用script标签的src可以跨域请求,据说有src属性的都可以跨域请求,但script标签返回的 ...

  4. js处理的8种跨域方法

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  5. C#进阶系列——WebApi 跨域问题解决方案:CORS

    前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题.本篇主要从实例的角度分享下CORS解决跨域问题一些细节. WebApi系列文章 C#进阶系列— ...

  6. WebApi 跨域问题解决方案:CORS

    注:本文为个人学习摘录,原文地址:http://www.cnblogs.com/landeanfen/p/5177176.html 前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看W ...

  7. C#进阶系列——WebApi 跨域问题解决方案:CORS(转载)

    C#进阶系列——WebApi 跨域问题解决方案:CORS   阅读目录 一.跨域问题的由来 二.跨域问题解决原理 三.跨域问题解决细节 1.场景描述 2.场景测试 四.总结 正文 前言:上篇总结了下W ...

  8. 跨域学习笔记2--WebApi 跨域问题解决方案:CORS

    自己并不懂,在此先记录下来,留待以后学习... 正文 前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题.本篇主要从实例的角度分享下CORS解决跨 ...

  9. .net webapi跨域方法整理

    方法一 在Web.Config里面加上了配置信息: <httpProtocol> <customHeaders> <add name="Access-Contr ...

随机推荐

  1. TestComplete 14 百度网盘下载

    TestComplete 14 百度网盘下载 链接:https://pan.baidu.com/s/1g3imm9zFOCKnx5qqtUMl4g 二维码:

  2. [CSP-S模拟测试]:randomwalking(DP)

    题目传送门(内部题59) 输入格式 第一行一个数$n$表示点数.第二行$n$个数$A_i$.接下来$n−1$行,每行两个数$u,v$表示$u$和$v$有边直接相连. 输出格式 一个数表示最小花费的起点 ...

  3. Windows-Windows下使用Linux系统(WSL)

    Install Windows Subsystem for Linux (WSL) on on Windows 10 | Microsoft Docs WSL(Windows Subsystem fo ...

  4. C++内存修改器开源代码

    我们玩单机游戏时,游戏难度可能过大, 或者游戏已经比较熟练,想要增加游戏的玩法,这时候可以使用修改器. 内存式游戏修改器主要对游戏内存修改 修改时有两种方式,一是定时对内存数值进行修改.实现类似锁定的 ...

  5. vue2.0---最近总结

    1.用脚手架给运维部门搞了个小东西,重新温习了一遍牛逼又方便的vue-cli. webpack的东西不必关心太多,而且webpack最近也是出了最新的4.0版本.还是改变挺多的,对一些代码的格式要求更 ...

  6. Java解释器模式`

    解释器模式提供了一种评估计算语言语法或表达式的方法. 这种类型的模式属于行为模式. 这种模式涉及实现一个表达式接口,它告诉解释一个指定的上下文. 此模式用于SQL解析,符号处理引擎等. 实现示例 我们 ...

  7. tar.xz 解压

    解压tar.xz文件:先 xz -d xxx.tar.xz 将 xxx.tar.xz解压成 xxx.tar 然后,再用 tar xvf xxx.tar来解包. xz -d Python-3.7.1.t ...

  8. mac 支持rz sz

    安装 lrzsz brew install lrzsz 配置 iTerm2 安装完成后我们需要在 iTerm2 中使用的话,还需要一些配置 进入到 /usr/local/bin 目录下,下载两个脚本文 ...

  9. 2019年RTC大会记录

    小编近期在研究webRTC点对点通信技术,怀着学习的心态参加了2019年RTC大会,对所见所闻做下记录,不对的地方还请批评指正! 这次热门的话题是5G.WebRTC.AI对图像.音视频的相关处理,思科 ...

  10. java.nio.Buffer 中的 flip()方法

    在Java NIO编程中,对缓冲区操作常常需要使用  java.nio.Buffer中的 flip()方法. Buffer 中的 flip() 方法涉及到 Buffer 中的capacity.posi ...