所谓的跨域(Cross-Origin),究竟是什么?——你所不知道浏览器跨域的小知识

来源:互联网 发布:双色球杀红球算法 编辑:程序博客网 时间:2024/06/06 14:13

Ajax的跨域请求数据的问题,一直是前端开发者经常讨论的话题。翻看了很多博客文章,发现很多人认为ajax跨域问题是Ajax本身的一些缺陷导致的,还有人认为这是服务器对Ajax请求的拦截,不过这些认识都是不全面的。其实禁止跨域请求是浏览器本身的一种安全策略——换句话说,其实禁止跨域不是什么ajax缺陷,是浏览器会对JavaScript的跨域请求有一些限制。

一、一些和跨域有关的概念

1.同源策略(same-origin policy)

说到同源策略,不得不提到另外一个概念——源(Origin)。那什么是源的呢?源其实是是个域名(domain),一般请求网页的那个url的域名就会被制定为源——例如这篇博客页面的的源就是“http://blog.csdn.net”。如此看来同源策略就能很容易理解了,就是限制Javascript的Ajax请求与源不相同的url。

2.跨域资源共享(Cross-Origin-Resource-Sharing)

跨域资源共享(CORS)机制,是为了浏览器能更为安全的处理跨域请求,使其不受同源策略的限制。简单来说就是把需要允许跨域的源写入response头里的Access-Control-Allow-Origin。对应的源就可以实现跨域资源共享了。

二、允许跨域和禁止跨域的具体机制

我们可以写一个简单的例子来说明这个问题,用servlet写一个简单的接口:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {InputStream ipt = request.getInputStream();try (InputStreamReader isr = new InputStreamReader(ipt); BufferedReader br = new BufferedReader(isr)) {String line = null;StringBuilder sb = new StringBuilder();while ((line = br.readLine()) != null) {sb.append(line);}System.out.println(sb.toString());} catch (IOException e) {e.printStackTrace();}response.getWriter().write("{\"response\": \"response you\"}");}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
之后把服务跑在127.0.0.1:8080下,之后用浏览器打开网上任意一个网页在控制台里发起对本地服务的ajax请求。很明显这是一个跨域的请求:
var xhr = new XMLHttpRequest();xhr.open('POST', 'http://127.0.0.1:8080/cors-demo/Cors');xhr.send('{"request": "hi"}');xhr.onload = function(e) {var xhr = e.target;console.log(xhr.responseText);}

浏览器控制台很快的返回了这个跨域常见的报错:

XMLHttpRequest cannot load http://127.0.0.1:8080/cors-demo/Cors. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://write.blog.csdn.net' is therefore not allowed access
其实,这个ajax请求是被服务端拿到了的,你是可以在后台的拿到前台send方法里面传入的{"request": "hi"}的,但是在Javascript里面却拿不到服务端的response。这应该怎么办呢?我们可以在服务端加上这句话:

response.addHeader("Access-Control-Allow-Origin", "http://write.blog.csdn.net");

这句话的意思是说,在response头里写入上述信息,允许源为“http://write.blog.csdn.net”的网页发起Ajax请求。之后便可以的发起跨域的ajax请求并正常的接受数据了。

综合前后端代码来看我们可以发现,其实这个request是发到服务端了,response也返回了客户端,但是浏览器会把当前网页的源与Access-Control-Allow-Origin里的url进行比较,如果发现有一样的url,就判定允许跨域访问,否则就无法在Javascript中拿到response信息,就会造成所谓的“禁止跨域访问”的现象。如果你想让一个web接口允许任何源的跨域访问,你就可以把头信息写成:Access-Control-Allow-Origin: *     —— “*”表示任意的源。其实浏览在禁止跨域的访问里报的异常也能很好的帮助我们理解这个问题,上文的报错信息的大概意思就是:没有在response的头信息里找到Access-Control-Allow-Origin这个属性,所以源 “****” 没有权限访问 ”*****“ url。


三、为什么jsonp能解决跨域问题

不过大部分前端开发人员一遇到跨域问题第一反应想到的解决方案还是jsonp。jsonp是个非正式的传输协议,jsonp之所以能够绕过浏览器的同源策略是因为除了JavaScript里的Ajax和Fetch请求,其他的请求都不受同源策略的限制——换句话说除了ajax请求,网页中其他的如css,js脚本等资源文件的请求,不会因为跨域而被限制访问。jsonp正是利用了这一点,完成了跨域数据请求。
那如何制造一个jsonp的请求呢?下面是例子:
前端代码:
var callback = 'callBkFunc';this[callback] = function(result) {    console.log(result);}var JSONP = document.createElement('script');JSONP.type = 'text/javascript';JSONP.src = "http://127.0.0.1:8080/cors-demo/Cors?callback=" + callback;document.getElementsByTagName("head")[0].appendChild(JSONP);
大致流程就是声明一个script标签,并把资源路径设为我们想跨域访问的url。在声明一个方法名为“callBkFunc”的方法名,并把其作为一个参数传给后台。
服务端代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(request.getParameter("callback"));String callbackName = request.getParameter("callback");response.getWriter().write(callbackName + "({\"response\": \"response you\"});");}
在前端通过script标签向后台传了方法名之后,服务端代码用得到的这个方法名构造了一个动态的js脚本——也就是“callBkFunc(args)”。在args写的就是我们想传给前端的数据,之后前端就可以在callBkFunc定义的形参result里拿到后台传输给前端的数据了。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 上海医保卡丢了怎么办 户口转到西安后医保怎么办 上海医保卡掉了怎么办 上海医保本丢了怎么办? 新版医保卡丢了怎么办 武汉社保卡掉了怎么办 职工社保卡丢了怎么办 杭州社保卡丢了怎么办 农村医疗卡丢了怎么办 陕西省医保卡丢了怎么办 小孩社保卡掉了怎么办 社区医保本丢了怎么办 宝宝医保卡掉了怎么办 同煤医疗卡丢了怎么办 杭州医保卡丢了怎么办 新的医保卡丢了怎么办 二代医保卡丢了怎么办 老医保卡丢了怎么办 上海医保卡余额用完了怎么办 身份证丢了医疗报销怎么办 取公积金身份证丢了怎么办 身份证丢了怎么办就诊卡 人在外地怎么办农村社保卡 武汉医保卡丢了怎么办 济宁社保卡丢了怎么办 农村医疗本丢了怎么办 常熟医保卡丢了怎么办 农民社保卡丢了怎么办 常熟社保卡坏了怎么办 社保卡丢失补办期看病怎么办 社保卡补办期间看病怎么办 医保卡冻结了出院结算怎么办 住院医保卡钱不够怎么办 住院押金条丢了怎么办 急用新社保卡要怎么办 看病没带社保卡怎么办 医保卡掉了住院怎么办 厦门医保卡丢了怎么办 成都医保卡丢了怎么办 长春医保卡丢了怎么办 县城医保卡丢了怎么办