zoukankan      html  css  js  c++  java
  • AJAX跨域

    一、相关概念

    • 同源策略:是浏览器的一种安全策略,所谓同源是指域名、协议、端口完全相同,只有同源的地址才可以相互通过AJAX的方式请求
    • 跨域请求:不同源地址之间的访问就是跨域请求

    二、问题以及尝试解决

    ①AJAX

    • 不同源地址之间,默认不能相互发送AJAX请求,执行后,浏览器会报错,大意是说localhost域名无法向google.com域名请求数据。
    • 因为同源策略的限制,不同域名、协议(http、https)或者端口无法直接进行ajax请求。 同源策略只针对于浏览器端,浏览器一旦检测到请求的结果的域名不一致后,会堵塞请求结果。
    • 这里注意,跨域请求是可以发去的,但是请求响应response被浏览器堵塞了
      <script>
           /**
            * 当前页面访问地址:http://localhost/test.html
            * 希望请求地址:https://www.baidu.com/s?wd=%E8%B7%A8%E5%9F%9F&tn=93338132_hao_pg(百度搜索跨域)
            */
            var url='https://www.baidu.com/s?wd=%E8%B7%A8%E5%9F%9F&tn=93338132_hao_pg';
            $.get(url,function(res){
                console.log(res);
            })
        </script>

    ②img 可以发送不同源之间的请求,但是无法拿到响应结果

    <script>
           /**
            * 当前页面访问地址:http://localhost/test.html
            * 希望请求地址:https://www.baidu.com/s?wd=%E8%B7%A8%E5%9F%9F&tn=93338132_hao_pg(百度搜索跨域)
            */
            var url='https://www.baidu.com/s?wd=%E8%B7%A8%E5%9F%9F&tn=93338132_hao_pg';
            var img=new Image();
            img.src=url;
        </script>

    ③link 可以发送不同源之间的请求,但是无法拿到响应结果

        <script>
           /**
            * 当前页面访问地址:http://localhost/test.html
            * 希望请求地址:https://www.baidu.com/s?wd=%E8%B7%A8%E5%9F%9F&tn=93338132_hao_pg(百度搜索跨域)
            */
            var url='https://www.baidu.com/s?wd=%E8%B7%A8%E5%9F%9F&tn=93338132_hao_pg';
            var link=document.createElement('link');
            link.rel= 'stylesheet';//注意:link的真正含义是链入一个文档,通过rel属性申明链入文档与当前文档之间的关系
            link.href=url;
            document.body.appendChild(link);
        </script>

    ④script  可以发送不同源之间的请求,但是无法拿到响应结果,但是借助服务端,可以拿到数据作为js文件执行,这就是JSONP的原理

    三、JSONP解决方案

    ①概念:JSONP 是JSON with Padding的缩写,是一种借助于script标签发送跨域请求的技巧

    ②原理:在客户端借助script标签请求服务端的一个动态网页(php文件),服务端的这个动态网页返回一段带有函数调用的JavaScript全局函数调用的脚本,并将原来需要返回给客户端的数据传递进去

    ③案例实现(封装):

    <?php
        //从本地的MySQL数据库test中读取数据(表users)
        $conn=mysqli_connect('localhost','root','0000','test');
        $query=mysqli_query($conn,'select * from users');
        while($row=mysqli_fetch_assoc($query)){
            $data[]=$row;
        }
        //如果没有参数,以json格式返回这个数据
        if(empty($_GET['callback'])){
            header('Content-Type: application/json');
            echo json_encode($data);
            exit();
        }
        //申明数据类型是js文件
        header('Content-Type: application/javascript');
        $result=json_encode($data);
        
        //$_GET['callback]}为get方式通过问号传递过来的参数,即函数名
        $callback_name=$_GET['callback'];
        echo "{$callback_name}({$result})";
    ?>
    <script>
           /**
            * 当前页面访问地址:http://www.demo.me/test.html(通过虚拟主机配置www.demo.me域名)
            * 希望请求地址:http://www.test.me/test.php(通过虚拟主机配置www.test.me域名)
            */
           //封装jsonp函数
            function jsonp(url,params,callback){
                var funcName='jsonp_'+Date.now()+Math.random().toString().substr(2,5);
                if(typeof params==='object'){
                    var tempArr=[];
                    for(var key in params){
                        var value=params[key];
                        tempArr.push(key + "=" + value);
                    }
                    params = tempArr.join('&');
                }
                var script=document.createElement("script");
                script.src=url + '?' + params  +'&callback=' + funcName ;
                document.body.appendChild(script);
                window[funcName]=function(data){
                    callback(data);
                    document.body.removeChild(script);
                }
            }
        //调用jsonp函数
        jsonp('http://www.test.me/test.php',{id:1},function(res){
            console.log(res);
        })
        </script>

    ④总结:由于XMLHttpRequest无法发送不同源之间的跨域请求,所以找到一种通过script标签发送跨域请求的方案,这种方案就是JSONP,JSONP需要服务端的配合,服务端按照客户端的要求返回一段JavaScript调用客户端的函数,只能发送GET请求,因为JSONP用的是script标签,跟AJAX提供的XMLHttpRequest没有任何的关系

    ⑤jQuery中使用JSONP

        <script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
        <script>
           /**
            * 当前页面访问地址:http://www.demo.me/test.html(通过虚拟主机配置www.demo.me域名)
            * 希望请求地址:http://www.test.me/test.php(通过虚拟主机配置www.test.me域名)
            */
           //jquery中使用JSONP就是将dataType设置为jsonp
            $.ajax({
                url: 'http://www.test.me/test.php',
                dataType: 'jsonp',
                success: function(res){
                    console.log(res)
                }
            })
        </script>

    ⑥其他AJAX封装库: Axios

    五、CORS(Cross Origin Resource Share)解决方案

    ①用法:这种方法无需客户端做出任何变化(客户端不用改代码),只要在被请求的服务器响应的时候添加一个的响应头,表示这个资源是否允许指定域请求

     header('Access-Control-Allow-Origin: *')

    ②案例实现

    <?php
        //从本地的MySQL数据库test中读取数据(表users)
        $conn=mysqli_connect('localhost','root','0000','test');
        $query=mysqli_query($conn,'select * from users');
        while($row=mysqli_fetch_assoc($query)){
            $data[]=$row;
        }
        //==============================================
        header('Access-Control-Allow-Origin: *');
        //==============================================
        header('Content-Type: application/json');
        echo json_encode($data);
    ?>
        <script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
        <script>
           /**
            * 当前页面访问地址:http://www.demo.me/test.html(通过虚拟主机配置www.demo.me域名)
            * 希望请求地址:http://www.test.me/test.php(通过虚拟主机配置www.test.me域名)
            */
            $.get('http://www.test.me/test.php',{},function(res){
                console.log(res);
            })
        </script>
  • 相关阅读:
    ideal配置使用Git
    git帮助和小结
    Git的配置
    Git安装
    navicat下载安装和激活一分钟完成
    eclipse安装svn插件
    [数据结构
    [数据结构
    Qt对话框之二:模态、非模态、半模态对话框
    Qt 窗口操作函数(置顶、全屏,最大化最小化按钮设置等)
  • 原文地址:https://www.cnblogs.com/EricZLin/p/9231983.html
Copyright © 2011-2022 走看看