cors跨域问题
同源策略:
是由NetScape提出的著名的安全策略,所有支持javaScript的浏览器都使用这个策略。同源策略限制了一个源中加载文本或脚本与来自其它源中资源的交互方式。
IE特例:
授信范围(Trust Zones):两个相互之间高度互信的域名,如公司域名(corporate domains),不遵守同源策略的限制。
端口:IE未将端口号加入到同源策略的组成部分之中,因此 http://company.com:81/index.html 和http://company.com/index.html 属于同源并且不受任何限制。
以上参考自MDN。
所谓同源是指:域名、协议、端口都相同。同源策略是浏览器最核心也最基本的安全功能
。这是知乎上关于同源策略的一篇文章。。但是浏览器在安全性和实用性上做出了让步,img/script/style/iframe等有src属性的都可以跨域引用资源。
方案一——通过JSONP跨域
jsonp是JSON with padding的简写,看起来与json差不多,但是包含在函数调用中的json,利用动态script元素来使用(具有src属性的如img,iframe,srcipt都不受同源策略的影响)。该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
如果使用jquery,可以在type为get的时候dataType设为jsonp,就可以了。
$.ajax({
url: 'http://www.qdaily.com/get_user_and_radar.json?winWidth=1280&winHeight=800',
type: 'get',
dataType: 'jsonp',
data: {},
})
.done(function(data) {
console.log(data.status);
})
然后,很幸运的就可以看到这个:
但是可以看出其实是请求到数据的,只是没有执行我们的callBack函数。
因为前面有提到:服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,也就是服务端的返回需要拼接成这样(比如函数名叫做haddleData):
haddleData({"status":true,subscribes:["12","23"]})
另外:jquery的ajax方法可以传入两个参数
jsonp : "callback"//设置这个会替换浏览器发送请求时地址后面自动添加的?callback=xxx中的callback这个字,一般情况下不用传这个参数
jsonpCallback: "success_jsonpCallback"//这个值将用来取代jQuery自动生成的随机函数名,也就是上句话中的'xxx'。
【这儿遗留了一个问题,还请各位解决】如果jsonpCallback不手动设置的话,jquery是会自动生成个随机的字符串的,但是服务器那边的函数名要写什么,回调函数才会正确的执行呢?
看一个运行成功的实例:
$.ajax({
url: 'http://localhost:8000/remote/remote.js',
type: 'get',
dataType: 'jsonp',
jsonp: 'back',
jsonpCallback: "haddleData",
data: {},
})
.done(function(data) {
console.log(data.status);
})
//这段程序运行在8080端口的
remote.js作为远端其中写了句
haddleData({"status":true,subscribes:["12","23"]})
对于大部分js初学者,大多使用jquery,而对原生不太熟悉。但是须知,ajax和jsonp其实本质上是不同的东西,ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本,利用脚本下载下来后立即执行的事实实现callback方法的调用。
原生js的jsonp简单实现:
<script>
function haddleData(data){
console.log(data.status);
}
</script>
<script type="text/javascript" src="http://localhost:8000/remote/remote.js"></script>
当然有多个本地函数需要处理的时候,加上回调函数名才是方便的,像这样:
<script type="text/javascript" src="http://localhost:8000/remote/remote.js?callback=haddleData"></script>
加上callback参数,可以使得服务器端根据前端指定的方法名cb动态返回cb(data)
;而不是都写死handleData(data)
;
【总结下jsonp】:
- 优点:
简单,函数回调在本地处理; - 缺点:
1、安全性(存在注入漏洞,如CSRF,XSS);
2、如果出现错误,不会像http请求那样有状态码;
3、只能使用get请求;
方案二——CORS(Cross-Origin Resource Sharing)
这是一个W3C标准(显然比jsonp背景深厚许多),同样需要浏览器和服务器同时支持,但是整个通信过程,都是浏览器自动完成,不需要用户参与,就像平时写Ajax一样(如果使用的是jquery的话)。
下面是原生js实现CORS的代码
function createCORSRequest(method,url){
var xhr=new XMLHttpRequest();
if("withCredentials" in xhr){
xhr.open(method,url,true);
}else if(typeof XDomainRequest != "undefined"){//IE10之前的版本使用XDmainRequest支持CORS
xhr=new XDomainRequest();
xhr.open(method,url);
}else{
xhr=null;
}
return xhr;
}
var request=createCORSRequest("get","待访问的地址");
if(request){
request.onload=function(data){
//do sth
};
request.send();
}
适用场景:
承载的信息量大,get形式搞不定,需选用post传输。CORS支持所有类型的传输。
兼容性:
移动端全面支持(除opera mini),PC上IE8+。
CORS思想:
使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。(请求和响应都不包含cookie)
当然如果设置成下面这样,所有的跨域都可以实现了,但这样毕竟太不安全。
"Access-Control-Allow-Origin:*";//允许任何域向我们的服务器发送请求
一般情况下,浏览器发送一个额外的Origin头部(由浏览器自动生成发送)
Origin:http://localhost:8080//本地网址
然后由服务器发送一个响应表头:Access-Control-Allow-Origin,如果服务器接收该请求,返回值(只能是通配符或单域名。)就和请求值一样。
Access-Control-Allow-Origin:http://localhost:8080
=>CORS方案的重点其实就在于服务器端的配置。
简单请求
- 只使用 GET, HEAD 或者 POST 请求方法。
如果使用 POST 向服务器端传送数据,则数据类型(Content-Type)只能是 application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种。
- 不会使用自定义请求头(类似于 X-Modified 这种)。
HTTP头部信息不超出以下{Accept,Accept-Language,Content-Language,Last-Event-ID,content-type(只限于上面提到的3种类型)}
对于简单请求,浏览器直接发出CORS请求。浏览器会自动在头信息(Request Headers)中,添加一个Origin 字段,来表明本次请求来自哪个域。
如果这个源不在许可范围内,会报错: No 'Access-Control-Allow-Origin' header is present on the requested resource.
如果Origin指定的域名在许可范围内(必须是跨域了的),Response Headers中会多出几个头信息字段。
Access-Control-Allow-Credentials:true//值为true表示允许发送cookie
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:http://localhost:8080
Access-Control-Max-Age:1728000
withCredentials属性
因为CORS默认不发送cookie和http认证,如果要把Cookie发到服务器,就要指定Access-Control-Allow-Credentials:true;
另外AJAX中也要打开withCredentials属性。
var xhr=new XMLHttpRequest();
xhr.withCredentials=true;
jquery ajax请求参数中加入
xhrFields: {
withCredentials: true
}
非简单请求
除了上面说的简单请求外都是非简单请求,比如:请求方法是PUT
或DELETE,或者Content-Type字段的类型是application/json,又或者有自定义请求头Access-Control-Request-Headers: X-Custom-Header。
比如,我添加自定义请求头
xhr.setRequestHeader('Some-Custom-Response-Header', 'value');
就会发现连续向同一地址请求了两次,而第一次请求什么值也没拿到
第二次请求
这是因为浏览器发现,这是一个非简单请求,就自动发出一个"预检"请求,要求服务器确认可以这样请求。"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。"预检"请求之后,浏览器球会进行正常CORS请求。
服务器端配置(rails为例)
1、可以参考这个方法:为 RESTful API 配置 CORS 实现跨域请求,写的挺详细的。然而对于rails并不算熟悉的我来说,有gem包,怎么可能放着不用呢~
2、这是Rack CORS 中间件的项目地址,按照文档的说明1分钟就可以基本搞定。
【问题:】
当我请求方式为put时,却出现了404错误,是因为没有为options提供路由么?
rails中使用CORS中的功能和细节还有很多,等到需要时再行挖掘吧,欢迎使用过的各位一起交流问题。
作者:RichardBillion
链接:https://www.jianshu.com/p/7257e7c60ef5
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
cors跨域问题的更多相关文章
- 如何在ASP.NET Core中实现CORS跨域
注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...
- ajax——CORS跨域调用REST API 的常见问题以及前后端的设置
RESTful架构是目前比较流行的一种互联网软件架构,在此架构之下的浏览器前端和手机端能共用后端接口. 但是涉及到js跨域调用接口总是很头疼,下边就跟着chrome的报错信息一起来解决一下. 假设:前 ...
- Web APi之手动实现JSONP或安装配置Cors跨域(七)
前言 照理来说本节也应该讲Web API原理,目前已经探讨完了比较底层的Web API消息处理管道以及Web Host寄宿管道,接下来应该要触及控制器.Action方法,以及过滤器.模型绑定等等,想想 ...
- Web API 实现JSONP或者安装配置Cors跨域
前言 照理来说本节也应该讲Web API原理,目前已经探讨完了比较底层的Web API消息处理管道以及Web Host寄宿管道,接下来应该要触及控制器.Action方法,以及过滤器.模型绑定等等,想想 ...
- CORS 跨域 实现思路及相关解决方案
本篇包括以下内容: CORS 定义 CORS 对比 JSONP CORS,BROWSER支持情况 主要用途 Ajax请求跨域资源的异常 CORS 实现思路 安全说明 CORS 几种解决方案 自定义CO ...
- 解决ajax请求cors跨域问题
”已阻止跨源请求:同源策略禁止读取位于 ***** 的远程资源.(原因:CORS 头缺少 'Access-Control-Allow-Origin').“ ”已阻止跨源请求:同源策略禁止读取位于 ** ...
- Asp.Net WebApi 启用CORS跨域访问指定多个域名
1.后台action指定 EnableCors指定可访问的域名多个,使用逗号隔开 //支持客户端凭据提交,指定多个域名,使用逗号隔开 [EnableCors("http://localhos ...
- Cors 跨域Access-Control-Allow-Origin
1.Access-Control-Allow-Origin 指定格式 The Origin header field has the following syntax: origin = " ...
- Asp.Net WebApi+Microsoft.AspNet.WebApi.Core 启用CORS跨域访问
WebApi中启用CORS跨域访问 1.安装 Nugget包Microsoft.AspNet.WebApi.Cors This package contains the components to e ...
- jsonp与cors跨域的一些理解
浏览器的同源策略,即是浏览器之间要隔离不同域的内容,禁止互相操作. 比如,当你打开了多个网站,如果允许多个网站之间互相操作,那么其中一个木马网站就可以通过这种互相操作进行一系列的非法行为,获取你在各个 ...
随机推荐
- problem:为什么会有options请求
为了安全考虑,浏览器对资源访问有同源限制的问题,也就是web应用程序只能访问和它同一协议同一域名同一端口的web应用程序上的资源. 通过跨域资源共享机制可以让资源在浏览器中访问与该资源本身不同域的资源 ...
- 使用jquery.mCustomScrollbar自定义滚动条(3)callback onCreate
碰到了一个问题,想简洁,所以在页面上使用 <div class="div_box mCustomScrollbar" data-mcs-theme="dark-3& ...
- 廖雪峰Java3异常处理-1错误处理-2捕获异常
1捕获异常 1.1 finally语句保证有无错误都会执行 try{...}catch (){...}finally{...} 使用try...catch捕获异常 可能发生异常的语句放在try{... ...
- 廖雪峰Java1-4数组操作-2数组排序
冒泡排序法 将第一个值和后面的值,挨个比较,如果手里的值比序列的值小,就交换数据,拿新的数字继续比较,直到最后. 再将第二个值和后面的值,挨个比较. 循环往复,排序完成. int[] ns = {28 ...
- Scrapy实战篇(八)之Scrapy对接selenium爬取京东商城商品数据
本篇目标:我们以爬取京东商城商品数据为例,展示Scrapy框架对接selenium爬取京东商城商品数据. 背景: 京东商城页面为js动态加载页面,直接使用request请求,无法得到我们想要的商品数据 ...
- Python3 文件的重命名
在Python3中我们要实现将本地文件homework.txt中的内容的修改操作时,大体的思路是这样的:先将homework.txt文件的内容读取到内存中,在内存中对里面的数据进行修改,接着将修改完成 ...
- Eclipse使用Maven创建Web时错误:Could not resolve archetype org.apache.maven.archetypes:maven-archetype-webap
网上也有好多方法我没有试成功,不过我将maven的conf setting.xml里的 阿里镜像给注释就可以了,你们也可以试试
- Css学习(2)
1 标签分类(显示方式) 块元素 典型代表,Div,h1-h6,p,ul,li 特点: ★独占一行 ★可以设置宽高 ★ 嵌套(包含)下,子块元素宽度(没有定义情况下)和父块元素宽度默认一致. 行内元素 ...
- 00012 - ps命令详解
使用权限:所有使用者使用方式:ps [options] [--help]说明:显示瞬间行程 (process) 的动态参数:ps的参数非常多, 在此仅列出几个常用的参数并大略介绍含义-A 列出所 ...
- [电脑知识点]Excel取消受保护视图