https://blog.csdn.net/hansexploration/article/details/80314948
http://www.cnblogs.com/yuzhongwusan/archive/2012/12/11/2812849.html
什么是跨域以及产生原因
跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。比如,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准
仅支持get操作的JSONP的产生过程:
1、Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>)。
2、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理。
3、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。
4、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
5、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。
6、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
我们看看以下几个实体, jsonp.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> // 得到航班信息查询结果后的回调函数 var flightHandler = function(data){ alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); }; // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; // 创建script标签,设置其属性 var script = document.createElement('script'); script.setAttribute('src', url); // 把script标签加入head,此时调用开始 document.getElementsByTagName('head')[0].appendChild(script); </script> </head> <body> </body> </html>
对应处理jsonp请求的后端代码,核心任务就是返回一个包括json数据的函数调用js代码。这段js代码会在web客户端执行,而flightHandler函数是在前端定义的。
echo ' flightHandler({ "code": "CA1998", "price": 1780, "tickets": 5 }'
JSONP一句话原理总结:
利用script标签绕过同源策略,获得一个类似以下的js函数调用,jsonpcallback是页面存在的回调方法,而数据就以函数参数的形式保存在callback函数参数中。
jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})
jsonp的缺点:
仅仅支持get请求
CORS:支持所有get, post跨域请求
从上面的讨论我们知道jsonp虽然可以一定程度上解决跨域的get请求数据访问问题,但是无法支持post操作。这时CORS就可以较好解决这个问题。但是CORS必须服务器配合配置来完成。
CORS的基本原理是客户端Origin头字段+服务器的以下配置实现
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
NGINX反向代理完美解决跨域问题
上面已经说到,禁止跨域问题其实是浏览器的一种安全行为,而现在的大多数解决方案都是用标签可以跨域访问的这个漏洞或者是技巧去完成,但都少不了目标服务器做相应的改变,而我最近遇到了一个需求是,目标服务器不能给予我一个header,更不可以改变代码返回个script,所以前5种方案都被我否决掉。最后因为我的网站是我自己的主机,所以我决定搭建一个nginx并把相应代码部署在它的下面,由页面请求本域名的一个地址,转由nginx代理处理后返回结果给页面,而且这一切都是同步的。