常用跨域方法总结(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. 用 Flask 来写个轻博客 (20) — 实现注册表单与应用 reCAPTCHA 来实现验证码

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 reCAPTCHA 应用 reCAPTCHA 前文列表 用 Flask ...

  2. 重新认识Maven

    PS:第一次接触maven大约是两年前吧,隐约记得之前都是人工寻找并下载很多jar,放在项目的lib中(表示太年轻,没有接触过Ant或者其他类似的工具,就不找别人写的比较了).懒人永远有着自己的小聪明 ...

  3. USACO 5.5 章节

    Picture 题目大意 IOI 1998 求n (<=5000)个矩形 覆盖的图形 的周长(包括洞), 坐标范围[-10000,10000] 题解 一眼离散化+2维线段树,但仔细一想 空间不太 ...

  4. Win10自动更新关闭

    1.在win7和win8的系统中我们可以很轻松的通过控制面板的中的Windows Update中找到关闭自动更新的选项, 但是在win10中我们是找不到的.如下图: 2.在win10中的设置里面我们也 ...

  5. Robot Framework 执行结果无法查看(tomcat部署)

    打开jenkins系统管理-命令行执行: System.setProperty("hudson.model.DirectoryBrowserSupport.CSP","& ...

  6. matplotlib系列——中文显示

    幕布视图:https://mubu.com/doc/alG8r_3iSw 参考文献:嵩天的Python课程讲义 方式一: 示例 rcParams的属性 方式二:(推荐使用) 示例: 中文字体种类

  7. 45-python基础-python3-字符串-常用字符串方法(三)-startswith()-endswith()

    4-字符串方法 startswith()和 endswith() startswith()和 endswith()判断字符串是否以某个字符串开始或结尾,存在返回 True,否则,方法返回 False. ...

  8. Codeforces 492B Name That Tune ( 期望DP )

    B. Name That Tune time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  9. Rikka with Nickname (简单题)

    Rikka with Nickname  链接:https://www.nowcoder.com/acm/contest/148/J来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒空间限制:C/ ...

  10. java并发编程之美-阅读记录4

    java并发包中的原子操作类,这些类都是基于非阻塞算法CAS实现的. 4.1原子变量操作类 AtomicInteger/AtomicLong/AtomicBoolean等原子操作类 AtomicLon ...