Ajax-跨域

本文介绍了浏览器的同源策略及其对跨域的影响,详细阐述了Ajax跨域的三种解决方案:1. 代理(后台解决);2. JSONP(针对GET方式);3. XHR2(IE10以下不支持)。重点讲解了JSONP的工作原理、优点和局限性,包括其错误处理缺失和安全性问题。并提供了一个JQ应用JSONP的实例,以及如何通过修改响应头利用XHR2进行跨域访问。总结指出,代理最通用但复杂,JSONP简单但仅限GET,XHR2简单但仅适用于HTML5环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个域名地址的组成:
这里写图片描述
浏览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。当协议、子域名、主域名、端口号中任意一个不同时,都算做不同域,不同域之间相互请求资源,就算做“跨域”。

跨域解决方法:
1、代理(后台解决);
2、JSONP(针对 GET 方式);
3、XHR2(IE10以下不支持)。

JSONP

Jsonp原理:
首先在客户端注册一个callback, 然后把callback的名字传给服务器。此时,服务器先生成 json 数据。然后以 javascript 语法的方式,生成一个function,function 名字就是传递上来的callback的名字。最后将事先生成的 json 数据直接以参数的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。客户端浏览器解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里。

JSONP实例:百度搜索

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <style type="text/css">
            *{ margin: 0; padding: 0;}
            #q{ display: block; width: 300px; height: 30px; border: 1px solid #e1e1e1; margin: 50px auto 0;}
            #ul1{ list-style: none; width: 300px; border: 1px solid #EDEDED; margin: -1px auto 0; display: none;}
            #ul1 li a{ display: block; height: 30px; line-height: 30px; padding: 0 5px; text-decoration: none; color: #666;}
            #ul1 li a:hover{ background: #ededed;}
        </style>
        <script type="text/javascript">
            function jsonpCallback(data){
                var oUl=document.getElementById("ul1");
                var html='';

                if (data.s.length) {
                    oUl.style.display='block';
                    for (var i=0; i<data.s.length; i++) {
                        html+='<li><a target="_blank" href="https://www.baidu.com/s?wd='+ data.s[i] +'">'+ data.s[i] +'</a></li>';
                    }
                    oUl.innerHTML=html;
                }else{
                    oUl.style.display='none';
                }
            }
            window.onload=function(){
                var oQ=document.getElementById("q");
                var oUl=document.getElementById("ul1");

                oQ.onkeyup=function(){
                    if (this.value!='') {
                        var oScript=document.createElement('script');
                        oScript.src='https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?json=1&cb=jsonpCallback&wd='+this.value;
                        document.body.appendChild(oScript);
                    }else{
                        oUl.style.display='none';
                    }

                }
                document.onclick=function(){
                    oUl.style.display='none';
                }
            }
        </script>
    </head>
    <body>
        <input id="q" type="text" />
        <ul id="ul1">
            <!--<li><a target="_blank" href="#">11</a></li>
            <li><a target="_blank" href="#">22</a></li>
            <li><a target="_blank" href="#">33</a></li>-->
        </ul>
    </body>
</html>

JSONP并不是所有跨域通信需求的万灵药,它有一些缺陷。
第一,也是最重要的一点,没有关于 JSONP 调用的错误处理。如果动态脚本插入有效,就执行调用;如果无效,就静默失败。失败是没有任何提示的。例如,不能从服务器捕捉到 404 错误,也不能取消或重新开始请求。
JSONP 的另一个主要缺陷是被不信任的服务使用时会很危险。因为 JSONP 服务返回打包在函数调用中的 JSON 响应,而函数调用是由浏览器执行的,这使宿主 Web 应用程序更容易受到各类攻击。

JQ应用JSONP的实例:上文中的案例,当把GET方法中请求的url由”http://localhost/ajaxdemo/server.php“改为”http://127.0.0.1/ajaxdemo/server.php“之后,就出现了跨域问题。

解决之后的前端代码:

<script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.js"></script>
<script>
$(document).ready(function(){

    $('#search').click(function(){
        $.ajax({
            type:"GET",
            url:"http://127.0.0.1/ajaxdemo/server.php?number=" + $('#keyword').val()+"&"+ Math.random(),
            dataType:'jsonp',
            jsonp:'callback',
            success:function(data){
                if (data.success) {
                    $('#searchResult').html(data.msg);
                }else{
                    $('#searchResult').html('出了错误:'+data.msg);
                }
            },
            error:function(jqXHR){
                alert("发生错误:" + jqXHR.status);
            }
        });
    })
})
</script>

可以看出前端代码仅修改增加了以下代码字段:

dataType:'jsonp',
jsonp:'callback',

服务端代码修改后为:

<?php
header("Content-Type: application/json;charset=utf-8"); 
$staff = array
    (
        array("name" => "洪七", "number" => "101", "sex" => "男", "job" => "总经理"),
        array("name" => "郭靖", "number" => "102", "sex" => "男", "job" => "开发工程师"),
        array("name" => "黄蓉", "number" => "103", "sex" => "女", "job" => "产品经理")
    );

if ($_SERVER["REQUEST_METHOD"] == "GET") {
    search();
} elseif ($_SERVER["REQUEST_METHOD"] == "POST"){
    create();
}

function search(){
    $jsonp=$_GET["callback"];

    if (!isset($_GET["number"]) || empty($_GET["number"])) {
        echo $jsonp.'({"success":false,"msg":"参数错误"})';
        return;
    }

    global $staff;

    $number = $_GET["number"];
    $result = '{"success":false,"msg":"没有找到员工"}';

    foreach ($staff as $value) {
        if ($value["number"] == $number) {
            $result = $jsonp.'({"success":true,"msg":"找到员工:员工编号:' . $value["number"] . 
                            ',员工姓名:' . $value["name"] . 
                            ',员工性别:' . $value["sex"] . 
                            ',员工职位:' . $value["job"] . '"})';
            break;
        }
    }
    echo $result;
}
?>

XHR2

HTML5中提供的XMLHttpRequest Level2(即XHR2)已经实现了跨域访问。但ie10以下不支持。

只需要在服务端填上以下响应头:

header("Access-Control-Allow-Origin:*");
/*星号表示所有的域都可以接受,*/
header("Access-Control-Allow-Methods:GET,POST");

总结:代理实现最麻烦,但使用最广泛,任何支持AJAX的浏览器都可以使用这种方式。JSONP相对简单,但只支持GET方式调用。XHR2最简单,但只支持HTML5,如果是移动端开发,可以选择使用XHR2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值