CORS(跨域资源共享)

摘要:
引用自阮一峰的网络日志:http://www.ruanyifeng.com/blog/2016/04/cors.html侵删一、浏览器将CORS请求(通过ajax方式)分成两类:1.简单请求:需要同时满足以下两大条件1).请求方法为:HEAD、GET、POST之一2).HTTP的请求头信息不超出以下字段:Accept、Accept-Language、Content-Language、Last-Ev

引用自阮一峰的网络日志:http://www.ruanyifeng.com/blog/2016/04/cors.html 侵删

一、浏览器将CORS请求(通过ajax方式)分成两类:

1.简单请求:需要同时满足以下两大条件

1).请求方法为:HEAD、GET、POST之一

2).HTTP的请求头信息不超出以下字段:Accept、Accept-Language、Content-Language、Last-Event-ID、

Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain

2.非简单请求:凡是不同时满足上面两个条件的都属于非简单请求

二、简单请求

浏览器直接发出CORS请求,在头信息中添加一个Origin字段:

// 该站点发送的ajax请求

GET /x/web-interface/online HTTP/1.1Host: api.bilibili.com
Connection: keep-alive
Accept: */*Origin: https://bangumi.bilibili.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Referer: https://bangumi.bilibili.com/anime/5978/play
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8

通过Origin字段说明本次请求来自哪个源,服务器根据这个值,决定是否同意这次请求

// 正常的响应头

HTTP/1.1 200 OK
Date: Thu, 07 Dec 2017 14:33:56GMT
Content-Type: application/json;charset=utf-8
Content-Length: 269Connection: keep-alive
Access-Control-Allow-Origin: https://bangumi.bilibili.com
Access-Control-Allow-Credentials: trueAccess-Control-Allow-Headers: Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma,Last-Modified,Cache-Control,Expires,Content-Type,Access-Control-Allow-Credentials
X-Cache: BYPASS from cn-sccd2-cmcc-w-02.hdslb.com
响应头中与CORS请求相关字段
Access-Control-Allow-Origin: 必须的字段;要求值是请求的Origin的值;或者为*,表示可任意跨域
Access-Control-Allow-Credentials:可选的字段;布尔值(默认无该字段);表示是否允许发送cookie,默认情况下cookie不包括在CORS请求中;
若设置为true表示服务器明确许可,cookie可以包含在请求中一同发送给服务器
Access-Control-Allow-Headers
Access-Control-Expose-Headers:可选字段;CORS请求时,XHR对象的getResponseHeader() 方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma;
如果想要拿到其他字段,就需要在这个字段中指定

如果Origin指定的源不在许可范围,服务器也会返回一个正常的HTTP回应,但是浏览器会发现响应头中没有包含

指定字段: Access-Control-Allow-Origin字段,或者与请求头中的Origin不匹配,就会知道出错了

// 通过本地服务器向 发送http://www.bilibili.com/x/web-interface/online ajax请求的请求头

Accept:*/*Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Host:api.bilibili.com
Origin:http://127.0.0.1:7824
Referer:http://127.0.0.1:7824/hello.html
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

// 通过本地文件 发送http://www.bilibili.com/x/web-interface/online ajax请求的请求头

Accept:*/*Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Host:api.bilibili.com
Origin:null
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

//服务器可以进行响应; 但是因为请求头的Origin和响应头Access-Control-Allow-Origin: https://bangumi.bilibili.com(或响应头无该字段) 不相符,浏览会进行报错;不会处理结果

HTTP/1.1 200 OK
Date: Thu, 07 Dec 2017 15:19:21GMT
Content-Type: application/json;charset=utf-8
Content-Length: 269Connection: keep-alive
X-Cache: BYPASS from cn-sccd2-cmcc-w-01.hdslb.com

CORS(跨域资源共享)第1张

三、非简单请求

非简单请求是一种 对服务器有特殊要求的请求;比如说PUT或DELETE等请求,或者Content-Type字段类型为application/json

非简单请求会在正是通信之前,增加一次HTTP查询请求(预检preflight)

询问服务器当前域名是否在服务器许可名单当中,以及可以使用的哪些HTTP动词和字段;只有得到肯定答复,浏览器才会正是的发出ajax请求,否则报错;

// put 请求

    var url = 'http://api.alice.com/cors';
    var xhr = newXMLHttpRequest();
    xhr.open('PUT', url, true);
    xhr.setRequestHeader('X-Custom-Header', 'value'); // 自定义头
    xhr.send();

预检请求头

OPTIONS /cors HTTP/1.1Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

预检请求的方法是OPTIONS;表示这个请求是用来询问的,头信息中关键字Origin表示来源

请求头字段

1.Access-Control-Request-Method:表示CORS请求会用到哪些HTTP方法

2.Access-Control-Request-Headers:指定浏览器CORS请求会发送的头信息字段

预检响应

服务器确认允许跨域请求时,就可以做出回应

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0Keep-Alive: timeout=2, max=100Connection: Keep-Alive
Content-Type: text/plain

如果浏览器否定预检请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段,浏览器会认定浏览器不太同意预检请求,会触发一个错误

响应头字段

1.Access-Control-Allow-Methods:必须字段;逗号分隔字符串;表明服务器支持的所有跨域请求的方法;避免多次预检请求

2.Access-Control-Allow-Headers:如果请求中包含Access-Control-Request-Headers字段,该字段为必须字段

3.Access-Control-Allow-Credentials:同简单请求

4.Access-Control-Max-Age:可选字段;指定预检有效期

通过预检请求后,以后每次浏览器的CORS请求就和简单请求一样会有一个Origin头信息字段

//本地非简单请求

CORS(跨域资源共享)第2张

// 本地服务器非简单请求结果

CORS(跨域资源共享)第3张

// 该站点非简单请求

CORS(跨域资源共享)第4张

CORS与JSONP都是用于跨域的,但是更为强大,支持所有类型的HTTP请求;

而JSONP的优势在于支持老式浏览器,以及向不支持CORS的网站去请求数据

免责声明:文章转载自《CORS(跨域资源共享)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Bootstrap入门(二十二)组件16:列表组【手把手教你】win10 虚拟机 VMware Workstation Pro 15下安装Ubuntu 19.04下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

简单对象访问协议(SOAP)初级指南[转]

这篇文章带你全面回顾对象远程进程调用(ORPC)技术的历程,以帮助你理解SOAP技术的基础,以及它克服存在技术(如CORBA和DCOM)的许多缺陷的方法。随后讲述详细的SOAP编码规则,并把焦点放在SOAP是怎样映射到存在的ORPC概念上的。   引言:   当我在1984年开始把计算作为我的职业的时候,大多数程序员并不关心网络协议。但是在九十年代网络变得...

在HTTP通讯过程中,是客户端还是服务端主动断开连接?

比如说:IE访问IIS,获取文件,肯定是要建立一个连接,这个连接在完成通讯后,是客户端Close了连接,还是服务端Close了连接。我用程序测模拟IE和IIS,都没有收到断开连接的消息,也就是都没有触发OnClose事件。我是用Socket建立的连接。如果两方面都没有主动断开连接,那么我猜测可能是传输的数据中有结束的标志,请问这个标志是怎样的?谢谢各位。...

Access数据库 字段值 字符替换

两种方法: (一)Access数据库内部使用方法 Update 表 SET 字段=replace(字段,"原字符","替换字符") 示例: 假设表为biao、字段为content、原字符为xiazai.jb51.net、替换字符为down1.jb51.net, 那么相应的SQL语句如下:Update biao SET content=replace(co...

深入浅出Blazor webassembly 之API服务端保护

受保护 API 项目的思路是: 调用方先提交用户名和密码 (即凭证) 到登录接口, 由登录接口验证凭证合法性, 如果合法, 返回给调用方一个Jwt token.  以后调用方访问API时, 需要将该token 加到 Bearer Http 头上, 服务方验证该 token 是否有效, 如果验证通过, 将允许其继续访问受控API.  ============...

python 钉钉 消息推送 文件传输

1、消息推送 钉钉群添加机器人 方式一:钉钉 群设置添加 群设置 -> 智能群助手 -> 添加机器人 -- 自定义机器人 设置如下: 这里选择 自定义关键字 填写"消息推送" ,只有发送的消息包含了 这个关键字,才会推送这个消息 复制webhook,代码需要用到 defsend_massage(message): webhook =...

C# 创建表ACCESS表,添加修改字段

最开始以为access 修改字段信息,用 ALTER TABLE 语句就可以了, 打开access 文件执行了 ALTER TABLE user ALTER COLUMN address TEXT(10) 发现可以运行,于是乎,就用C#链接 数据库 OleDbConnection,OleDbCommand 去执行,可是字符串一模一样。 就是执行报错提示  ...