从跨域问题探究Ajax的GET请求和地址栏发起GET请求的区别

最近做的一个项目中,前后端分离,前端使用ajax方式来请求接口获取的json数据,但这不可避免会出现跨域的问题,这个问题以前也遇到过,一般解决方案是后端修改一下请求头部的Allow-Origin。

但这两天研究HTTP协议时,就花了点时间研究了一下这个跨域问题的来龙去脉。对跨域不了解的同学可以先看看阮一峰老师的这篇博客:http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html,讲的很细很全面。

对同源策略有所了解的同学,要解决跨域问题,最重要的是要了解哪些情况会造成同源限制?阮一峰老师的博客中总结了下面三点,我也参考了《白帽子讲Web安全》这本书提到的同源策略,做一些补充。

浏览器会对以下几种情况产生跨域限制:

(1) 读取Cookie、LocalStorage 和 IndexDB(毕竟两个完全不同的客户端要是能互相读取cookie,就太不安全了)。

(2) 获取DOM (如<iframe>,需要注意的是<script>、<img>、<src>、<href>这些标签可以跨域访问资源,只是这种方式的访问只能加载资源,不能读写资源。)。

(3) AJAX 请求(主要是ajax依赖于XMLHttpRequest(XHR))

这里我就着重说明一下ajax请求。

为什么浏览器会对ajax请求产生跨域限制呢?我还隐约记得以前刚学ajax时,老师教我们用原生js的方式来实现ajax请求,代码如下:

    //ajax发起get请求
    function getMethod(){
        var xhr= new XMLHttpRequest();//通过XMLHttpRequest创建ajax对象
        xhr.open("get","/getdata");//创建监听
        //监听ajax状态码
        xhr.onreadystatechange= funtion(){
            if(xhr.status==200 && xhr.readyState==4){
                var result = xhr.responseText;
                console.log(result); //获取请求的数据
            }
        }
        xhr.send(); //发送请求
    }
    //ajax发起post请求
    function postMehtod(){
        var p1 = "a";
        var p2 = "b";
        var xhr= new XMLHttpRequest();
        xhr.open("post","/login");
        //设置请求头类型
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        //监听ajax状态码
        xhr.onreadystatechange= function(){
            if(xhr.status==200 && xhr.readyState==4){
                var result = xhr.responseText;
                console.log(result);
            }
        }
        xhr.send("p1="+p1+"&p2="+p2);//带参发送请求
    }

不难看出,ajax能实现http请求和响应,主要依赖于 XMLHttpRequest(XHR)

在通过查文档可以找到,XHR是受到了同源策略的限制,参考文档:https://developer.mozilla.org/zh-cn/docs/web/api/xmlhttprequest,文档对XHR跨域没有做明确描述,但有两个属性描述提到过。

XMLHttpRequest.withCredentials

一个布尔值,用来指定跨域 Access-Control 请求是否应当带有授权信息,如 cookie 或授权 header 头。

XMLHttpRequest.mozSystem 只读

一个布尔值,如果为真,则在请求时不会强制执行同源策略。 

综上,不仅可以得到浏览器对XMLHttpRequest做出了同源策略限制的结论,而且了解到还可以通过修改头部信息的 Access-Control来规避这种限制。这就是为什么遇到ajax请求的跨域问题,我们通常都是在后端设置头部的Allow-Origin来解决。

那么问题来了,为什么通过ajax发起get请求去调用接口数据会造成跨域限制,而如果直接通过浏览器的地址栏访问接口的地址,却可以直接得到对应的json数据呢?

这个问题我在做开发时也琢磨了一段时间,后来才意识到,直接通过地址栏发起请求,对于服务器而言,这就是一个正常的浏览器请求,并不涉及到另一个域,而且也不存在一些背后的脚本攻击,所以浏览器并不会对这种请求加以限制。就像我们通过地址栏访问https://www.baidu.com一样,只是一个正常用户的请求,我们除了请求百度首页的数据外,并不能对百度做什么,所以浏览器默认这种方式是安全的。

当然了,做内部接口,安全起见,最好还是加上Token验证。

猜你喜欢

转载自blog.csdn.net/c_o_d_e_/article/details/113343903