关于前端开发的跨域问题以及解决方法jsonp

对于一名初级的Web前端开发工程师来说,刚进入这个行业应该会经历这样的一个面试问题,那就是跨域问题。

什么是跨域呢?首先我们先来了解一下域名地址这个概念。

  • 一个域名地址的组成:

    协议+子域名+主域名+端口号+请求资源
    http:// www . abc.com : 8080 / scripts/jquery.js

  • 当这几个中有任意一个不相同时,都算作不同域。

  • 不同域之间相互请求资源,我们就叫做“跨域”。
    比如:http://www.abc.com/index.html请求http://www.efg.com/service.php

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。因为JavaScript同源策略的限制,a.com域名下的js无法操作b.com或者是c.com域名下的对象。

比如:
www.abc.com/index.html 调用 www.abc.com/service.php( 非跨域 )
www.abc.com/index.html 调用 www.efg.com/service.php( 跨域 )
www.abc.com/index.html 调用 bbs.abc.com/service.php( 跨域 )
www.abc.com/index.html 调用 www.abc.com:81/service.php( 跨域 )
www.abc.com/index.html 调用 https://www.abc.com/service.php( 跨域 )

实例

客户端代码 jQueryAjax.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>jQuery封装的Ajax库</title>
        <style>
        body, input, select, button, h1 {
            font-size: 28px;
            line-height:1.7;
        }
        </style>
    </head>
    <body>
        <h1>员工查询</h1>

        <label>请输入员工编号:</label>
        <input type="text" id="keyword" />
        <button id="search">查询</button>
        <p id="searchResult"></p>

        <h1>员工新建</h1>
        <label>请输入员工姓名:</label>
        <input type="text" id="staffName" /><br>
        <label>请输入员工编号:</label>
        <input type="text" id="staffNumber" /><br>
        <label>请选择员工性别:</label>
        <select id="staffSex">
        <option></option>
        <option></option>
        </select><br>
        <label>请输入员工职位:</label>
        <input type="text" id="staffJob" /><br>
        <button id="save">保存</button>
        <p id="createResult"></p>
        <script type="text/javascript" src="jquery-1.12.1.js" ></script>
        <script>
            $(function(){
                $("#search").click(function(){
                    $.ajax({
                        type:"GET",
                        url:"http://localhost/AjaxDemo/serverjson.php?number="+$("#keyword").val(),
                        dataType:"json",
                        success:function(data){
                            if(data.success){
                                $("#searchResult").html(data.msg);
                            }else{
                                $("#searchResult").html("出现错误:"+data.msg);
                            }
                        },
                        error:function(jqXHR){
                            alert("发生错误:"+jqXHR.status);
                        },
                    });

                });
                $("#save").click(function(){
                    $.ajax({
                        type:"POST",
                        url:"http://localhost/AjaxDemo/serverjson.php",
                        data:{
                            name:$("#staffName").val(),
                            number: $("#staffNumber").val(), 
                            sex: $("#staffSex").val(), 
                            job: $("#staffJob").val()
                        },
                        dataType: "json",
                        success: function(data){
                            if (data.success) { 
                                $("#createResult").html(data.msg);
                            } else {
                                $("#createResult").html("出现错误:" + data.msg);
                            }  
                        },
                        error: function(jqXHR){     
                           alert("发生错误:" + jqXHR.status);  
                        },
                    });
                });
            });
        </script>
    </body>
</html>

服务器端代码 serverjson.php

<?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" => "产品经理")
    );

//判断如果是get请求,则进行搜索;如果是POST请求,则进行新建
//$_SERVER是一个超全局变量,在一个脚本的全部作用域中都可用,不用使用global关键字
//$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法
if ($_SERVER["REQUEST_METHOD"] == "GET") {
    search();
} elseif ($_SERVER["REQUEST_METHOD"] == "POST"){
    create();
}

//通过员工编号搜索员工
function search(){
    //检查是否有员工编号的参数
    //isset检测变量是否设置;empty判断值为否为空
    //超全局变量 $_GET 和 $_POST 用于收集表单数据
    if (!isset($_GET["number"]) || empty($_GET["number"])) {
        echo '{"success":false,"msg":"参数错误"}';
        return;
    }
    //函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问。
    //global 关键词用于访问函数内的全局变量
    global $staff;
    //获取number参数
    $number = $_GET["number"];
    $result = '{"success":false,"msg":"没有找到员工。"}';

    //遍历$staff多维数组,查找key值为number的员工是否存在,如果存在,则修改返回结果
    foreach ($staff as $value) {
        if ($value["number"] == $number) {
            $result = '{"success":true,"msg":"找到员工:员工编号:' . $value["number"] . 
                            ',员工姓名:' . $value["name"] . 
                            ',员工性别:' . $value["sex"] . 
                            ',员工职位:' . $value["job"] . '"}';               
            break;
        }
    }
    echo $result;
}

//创建员工
function create(){
    //判断信息是否填写完全
    if (!isset($_POST["name"]) || empty($_POST["name"])
        || !isset($_POST["number"]) || empty($_POST["number"])
        || !isset($_POST["sex"]) || empty($_POST["sex"])
        || !isset($_POST["job"]) || empty($_POST["job"])) {
        echo '{"success":false,"msg":"参数错误,员工信息填写不全"}';
        return;
    }
    //TODO: 获取POST表单数据并保存到数据库

    //提示保存成功
    echo '{"success":true,"msg":"员工:' . $_POST["name"] . ' 信息保存成功!"}';
}

?>

运行结果
这里写图片描述
这里写图片描述
说明此时访问是成功的。

接下来改成跨域访问
对上面客户端的代码做下小小的改动:

//GET
url:"http://127.0.0.1/AjaxDemo/serverjson.php?number="+$("#keyword").val(),
//POST
url:"http://127.0.0.1/AjaxDemo/serverjson.php",

运行结果:
这里写图片描述
因为域名发生了改变,所以构成了跨域访问。

处理跨域的方法–JSONP(JSON with padding )

JSONP 是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问问题。其原理是根据 XmlHttpRequest 对象受到同源策略的影响,而 <script>标签元素却不受同源策略影响,可以加载跨域服务器上的脚本,网页可以从其他来源动态产生 JSON 资料。用 JSONP 获取的不是 JSON 数据,而是可以直接运行的 JavaScript 语句。

不足:
只能使用 GET 方法发起请求,这是由于 script 标签自身的限制决定的。

客户端代码POST请求部分改为:

$("#search").click(function(){
                    $.ajax({
                        type:"GET",
                        url:"http://127.0.0.1/AjaxDemo/serverjson.php?number="+$("#keyword").val(),
                        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);
                        },
                    });

                });

服务器端代码:

<?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" => "产品经理")
    );

//判断如果是get请求,则进行搜索;如果是POST请求,则进行新建
//$_SERVER是一个超全局变量,在一个脚本的全部作用域中都可用,不用使用global关键字
//$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法
if ($_SERVER["REQUEST_METHOD"] == "GET") {
    search();
} elseif ($_SERVER["REQUEST_METHOD"] == "POST"){
    create();
}

//通过员工编号搜索员工

    $jsonp=$_GET["callback"];

    //检查是否有员工编号的参数
    //isset检测变量是否设置;empty判断值为否为空
    //超全局变量 $_GET 和 $_POST 用于收集表单数据
    if (!isset($_GET["number"]) || empty($_GET["number"])) {
        echo '{"success":false,"msg":"参数错误"}';
        return;
    }
    //函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问。
    //global 关键词用于访问函数内的全局变量
    global $staff;
    //获取number参数
    $number = $_GET["number"];
    //callback()注意有括号
    $result = $jsonp.'({"success":false,"msg":"没有找到员工。"})';

    //遍历$staff多维数组,查找key值为number的员工是否存在,如果存在,则修改返回结果
    foreach ($staff as $value) {
        if ($value["number"] == $number) {

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

            break;
        }
    }
    echo $result;
}

//创建员工
function create(){
    //判断信息是否填写完全
    if (!isset($_POST["name"]) || empty($_POST["name"])
        || !isset($_POST["number"]) || empty($_POST["number"])
        || !isset($_POST["sex"]) || empty($_POST["sex"])
        || !isset($_POST["job"]) || empty($_POST["job"])) {
        echo '{"success":false,"msg":"参数错误,员工信息填写不全"}';
        return;
    }
    //TODO: 获取POST表单数据并保存到数据库

    //提示保存成功
    echo '{"success":true,"msg":"员工:' . $_POST["name"] . ' 信息保存成功!"}';
}

?>

运行之后则成功了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值