常用跨域方法总结(2)——CORS
常用跨域方法总结(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
常用跨域方法总结(2)——CORS的更多相关文章
- 循序渐进Python3(十一) --6-- Ajax 实现跨域请求 jsonp 和 cors
Ajax操作如何实现跨域请求? Ajax (XMLHttpRequest)请求受到同源策略的限制. Ajax通过XMLHttpRequest能够与远程的服务器进行信息交互,另外 ...
- 前端Js跨域方法汇总—剪不断,理还乱,是跨域
1.通过jsonp跨域2.通过修改document.domain来跨子域(iframe)3.隐藏的iframe+window.name跨域4.iframe+跨文档消息传递(XDM)5.跨域资源共享 C ...
- 面试整理(2)跨域:jsonp与CORS
问题:跨域有哪些方法?jsonp的原理是什么? jsonp: 先说jsonp,jsonp的主要原理是利用script标签的src可以跨域请求,据说有src属性的都可以跨域请求,但script标签返回的 ...
- js处理的8种跨域方法
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- C#进阶系列——WebApi 跨域问题解决方案:CORS
前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题.本篇主要从实例的角度分享下CORS解决跨域问题一些细节. WebApi系列文章 C#进阶系列— ...
- WebApi 跨域问题解决方案:CORS
注:本文为个人学习摘录,原文地址:http://www.cnblogs.com/landeanfen/p/5177176.html 前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看W ...
- C#进阶系列——WebApi 跨域问题解决方案:CORS(转载)
C#进阶系列——WebApi 跨域问题解决方案:CORS 阅读目录 一.跨域问题的由来 二.跨域问题解决原理 三.跨域问题解决细节 1.场景描述 2.场景测试 四.总结 正文 前言:上篇总结了下W ...
- 跨域学习笔记2--WebApi 跨域问题解决方案:CORS
自己并不懂,在此先记录下来,留待以后学习... 正文 前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题.本篇主要从实例的角度分享下CORS解决跨 ...
- .net webapi跨域方法整理
方法一 在Web.Config里面加上了配置信息: <httpProtocol> <customHeaders> <add name="Access-Contr ...
随机推荐
- 文字在线中间,CSS巧妙实现分隔线的几种方法
单个标签实现分隔线: .demo_line_01{ padding: 0 20px 0; margin: 20px 0; line-height: 1px; border-left: 200px so ...
- JDK1.8 动态代理机制及源码解析
动态代理 a) jdk 动态代理 Proxy, 核心思想:通过实现被代理类的所有接口,生成一个字节码文件后构造一个代理对象,通过持有反射构造被代理类的一个实例,再通过invoke反射调用被代理类实例的 ...
- python中的装饰器基本理论
装饰器 : 本质上 是一个 函数 原则 : 1,不修改原函数的源代码 2,不修改原函数的调用方式. 装饰器的知识储备 装饰器 = 高阶函数 + 函数嵌套 +闭包 我的理解是,函数名也是一个变量,将函数 ...
- 2018 China Collegiate Programming Contest Final (CCPC-Final 2018)(A B G I L)
A:签到题,正常模拟即可. #include<bits/stdc++.h> using namespace std; ; struct node{ int id, time; }; nod ...
- JAVA中的面向对象与内存解析_2
构造方法(构造函数) • 使用new +构造方法创建一个新的对象. • 构造函数是定义在Java类中的一个用来初始化对象的函数. • 构造函数与类同名且没有返回值. • 例如:Person类的构造 ...
- 洛谷 P1197 [JSOI2008]星球大战——并查集
先上一波题目 https://www.luogu.org/problem/P1197 很明显删除的操作并不好处理 那么我们可以考虑把删边变成加边 只需要一波时间倒流就可以解决拉 储存删边顺序倒过来加边 ...
- 在Python中写入文件时,权限被拒绝错误
我想创建一个文件并在python中写一些整数数据.例如,我有一个变量abc = 3,我试图将它写入一个文件(它不存在,我假设python将自己创建): fout = open("newfil ...
- [fw]PAGE_SIZE & PAGE_SHIFT & _AC()
PAGE_SIZE & PAGE_SHIFT & _AC() 在大多系统下,PAGE_SIZE被定义为 4k 大小,即 4096 字节. 在 x86 系统里,PAGE_SIZE 和 P ...
- 【置顶】CSP/S 2019退役祭
标题没错,今年就是我的最后一年了. 才高一啊,真不甘心啊. DAY1(之前的看前几篇博客吧) T1 现在没挂 T2 貌似是树形DP,跑到80000的深度时挂了,于是特判了链的情况,大样例过了,现在没挂 ...
- vscode 常用命令行
Ctrl+Shift+P: 打开命令面板 打开一个新窗口: Ctrl+Shift+N 关闭窗口: Ctrl+Shift+W 新建文件 Ctrl+N 代码行缩进 Ctrl+[ . Ctrl+] 上下 ...