同源策略与CORS
同源策略
同源策略是浏览器保护用户安全上网的重要措施,协议、域名、端口号三者相同即为同源。
不同源下,浏览器不允许js操作Cookie、LocalStorage、DOM等数据或页面元素,也不允许发送ajax请求,同源下则不受影响。
下图是在Chrom控制台中发送ajax跨域请求的报错信息:

图片中黄色部分提示响应被阻止,说明在跨域的情况下,请求依然发送到了服务器且服务器返回了数据,只是被浏览器拦下了。
对于跨域问题可以使用CORS来解决,使用CORS时,HTTP请求分为两种情况:简单请求与复杂请求。
简单请求
满足以下三点即为简单请求:
- HTTP请求方法为GET、POST或HEAD
- HTTP请求头只能包含
Accept, Accept-Language, Content-Language, Content-Type或Last-Event-ID - ContentType的值只能为以下三种:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
复杂请求
除简单请求之外即为复杂请求。浏览器在发送复杂请求前会先发送Preflight request(预检请求),即发送OPTIONS请求。注意是浏览器发送的,用户无感。
预检请求头包含两个特定字段:
- Access-Control-Request-Method
表示后续请求会用到的HTTP方法,该字段必选 - Access-Control-Request-Headers
后续请求中所设置的请求头部信息,注意,这里不包含浏览器默认设置的头部字段,如:User-Agent。该字段可不发送。
服务器会检查对预检请求中的Origin、Access-Control-Request-Method、Access-Control-Request-Headers字段值,并返回正常的HTTP响应。
浏览器根据返回信息判断后续请求是否符合服务器端跨域要求,不符合则抛出错误信息。通过预检请求后,则发送后续请求,此时和简单请求无差别。
服务器配置CORS的几个字段
- Access-Control-Allow-Origin
必选,设置允许哪些源访问服务器资源 - Access-Control-Allow-Methods
必选,设置允许哪些HTTP方法 - Access-Control-Request-Headers
设置HTTP请求头中包含哪些字段,如果浏览器请求包括Access-Control-Request-Headers字段,则必选
以上三个字段为常用字段,其余字段配置参考:CORS policy options。
withCredentials与Cookie的跨域问题
Cookie受到同源策略的限制没有那么严格,默认情况下,只要发送请求方所在域与Cookie的Domain值相同即可将cookie发送至服务器端,无需考虑协议和端口号。在默认情况下,客户端发起的HTTP请求会带上目标域的Cookie,但无法携带其它属于其它的域Cookie。
我们可以借助XMLHttpRequest对象的withCredentials属性及CORS的Access-Control-Allow-Credentials二者来实现跨域的Cookie发送和写入。
var xhr=new XMLHttpRequest();
xhr.open('GET','http://www.target.com:8093/api/GetAllProductType');
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
console.log(xhr.response);
}
}
// 这里使用withCredentials属性来发送Cookie
xhr.withCredentials=true;
xhr.send();
注意,在使用withCredentials时,服务器端不能将Access-Control-Allow-Origin的值配置为*,否则客户端会报错:
Access to XMLHttpRequest at ''http://www.target.com:8093/api/GetAllProductType' from origin 'http://www.request.com:8094' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
一个问题
上周在ASP.NET Web API 2中使用CORS,报错:The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed。原因是服务器端配置了两次CORS,导致返回了两个Access-Control-Allow-Origin:*但浏览器只允许一个。
经过排查发现在Web.config文件中也配置了CORS,与代码中的配置重复,注释掉之后问题解决。该问题参考了:stackoverflow上的回答。
小结
同源策略是浏览器为保障用户(数据)安全而对JS功能进行一定限制。毕竟HTML与CSS只负责网页结构与样式,不具备操作页面元素及与服务器交互的功能。
离开浏览器环境后跨域问题也就不复存在。
严格的限制会导致一些不便,故同源策略开了几个口子:
Cookie共享
子域名可以共享父级域名的cookie嵌入式资源获取
<script>,<img>,<link>等标签获取资源不受同源策略限制,这也是JSONP实现跨域的原理
常用处理跨域请求的方式有JSONP和CORS:
JSONP
需要前后端协作处理且只支持GET请求
不是标准规范
对老式浏览器友好(这里想到了老古董IE:)CORS
支持GET、POST、PUT、DELETE等多种请求
服务器端配置简单且不需要前端写额外的代码
目前主流浏览器均支持CORS规范
推荐阅读
Enable Cross-Origin Requests (CORS) in ASP.NET Core
Cross-Origin Resource Sharing (CORS)
同源策略与CORS的更多相关文章
- 浏览器的同源策略及CORS跨域解决方案 DRF
一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 举个例子: 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示例: UR ...
- 同源策略、CORS
一.同源策略 同源策略(Same origin policy) 是一种约定, 它是浏览器最核心也是最基本的安全功能 , 如果缺少了同源策略, 则浏览器的正常功能可能都会受影响 , 可以说web是构建在 ...
- 同源策略与CORS跨域请求
一.同源策略 1.简介 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源 ...
- 同源策略 - JSONP - CORS
1. Jquery 对象可以通过 .index() 进行取出自当前元素在父级元素中存放的索引: 2. 浏览器的同源策略 -- Ajax 在访问非本网站的时候,在数据返回的时候,会被浏览器拦截 - 后 ...
- [CORS:跨域资源共享] 同源策略与JSONP
Web API普遍采用面向资源的REST架构,将浏览器最终执行上下文的JavaScript应用Web API消费者的重要组成部分."同源策略"限制了JavaScript的跨站点调用 ...
- Apache2 同源策略解决方案 - 配置 CORS
什么是同源策略 现在的浏览器大多配有同源策略(Same-Origin Policy),具体表现如下: 浏览某一网站,例如 http://www.decembercafe.org/.这个网页中的 Aja ...
- 关于安全性问题:(XSS,csrf,cors,jsonp,同源策略)
关于安全性问题:(XSS,csrf,cors,jsonp,同源策略) Ajax 是无需刷新页面就能从服务器获取数据的一种方法.它的核心对象是XHR,同源策略是ajax的一种约束,它为通信设置了相同的协 ...
- 同源策略 & 高效调试CORS实现
# 目录 为什么有同源策略? 需要解决的问题 CORS跨域请求方案 preflight withCredentials 附:高效.优雅地调试CORS实现 ----------------------- ...
- 同源策略jsonp和cors
同源策略: 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上 ...
随机推荐
- VMware虚拟机网络设置
背景介绍 在用 VMware workstation 安装好虚拟机后,需要给虚拟机配置网络,配置网络的方法有桥接.NAT. 采用桥接的方法需要占据物理机网段的ip地址,可能会与物理机同一网段的其 ...
- MFC在对话框中嵌入对话框
在对话框中嵌入子对话框 代码 m_childDlg = new CChildDlg(); m_childDlg->Create(IDD_CHILD_DIALOG,AfxGetApp()-> ...
- (PMP)第8章-----项目质量管理
过程质量管理,成果质量的管理 戴明理论:PDCA,戴明环 朱兰理论:质量规划,质量控制,质量改进,朱兰三部曲 克鲁斯比理论:零缺陷,质量免费 石川理论:质量圈,因果图,质量管理七大工具:核对表,帕累托 ...
- telnet的安装和使用
在日常使用中,有时候需要检测服务器上面的部分端口有没有打开,这个时候可以使用telnet进行调试.下面是一篇转载的文章. 原文地址:http://linuxtech.blog.51cto.com/36 ...
- SSM_CRUD新手练习(8)搭建BootStrap分页页面
经过Spring单元测试模拟请求,我们能够成功的取出数据,接下来,我们就开始写用来显示查询数据的分页页面吧. 我们使用Bootstrap来帮助我们快速开发漂亮的页面,具体怎么用可以查看Bootst ...
- EF6学习笔记(六) 创建复杂的数据模型
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇原文地址:Creating a More Complex Data Model 本篇讲的比较碎,很多内容本人 ...
- django扩展User认证系统
第一种方法proxy 如果你对Django提供的字段,以及验证的方法都比较满意,没有什么需要改的.但是只是需要在他原有的基础之上增加一些操作的方法.那么建议使用这种方式.示例代码如下: #在model ...
- GC垃圾回收机制,iOS内存管理。
问题: MRC中通过调用静态方法创建的新对象,不再使用时需要对其发送release消息吗? 不需要,因为约定静态方法创建的对象会自动将其放入自动释放池,即已对其发送autorelease消息,因此不可 ...
- AndroidStudio制作底部导航栏以及用Fragment实现切换功能
前言 大家好,给大家带来AndroidStudio制作底部导航栏以及用Fragment实现切换功能的概述,希望你们喜欢 学习目标 AndroidStudio制作底部导航栏以及用Fragment实现切换 ...
- linux常用的BootLoader U-boot的前世今生
U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目.U-Boot的作用是系统引导. U-Boot从FADSROM.8xxROM.PPCBOOT逐步发展演化而 ...