Jsonp跨域请求

本文介绍了浏览器的同源策略及产生的原因,并详细解析了三种主要的跨域解决方案:通过后台代理获取数据、CORS(跨域资源共享)和JSONP。通过实例展示了如何使用JSONP进行跨域请求。

浏览器的同源策略

URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。
三者有一个不同则会产生跨域。

跨域的几种解决方案

1,通过后台通过代理获取其它域名下的数据

2,CORS

CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

Access-Control-Allow-Origin 该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求

3,JSONP

JSONP和JSON不一样,它并不是一种数据格式。而一种JavaScript实现跨域数据访问的方式。

JSONP跨域的原理

在浏览器中,script、img、iframe、link等标签都可以加载跨域资源,而不受同源限制。
而Jsonp就是利用script标签可以加载外部标签这一特性来实现跨域请求。下面看一个小demo。

数据库如图:
这里写图片描述

php代码

<?php
    class Lists {
        public $id;
        public $name;
        public $url;
        public $country;
    }

    function connect() {
        $localhost = 'localhost';
        $username = 'root';
        $password = 'root';
        $database = '10086q';

        $con = mysqli_connect($localhost,$username,$password,$database);
        if (mysqli_connect_error($con)) {
            echo "连接错误".mysqli_connect_error();
            return null;
        }
        return $con;
    }


    $conn = connect();
    $sql = 'select * from websites';

    $res = mysqli_query($conn,$sql);
    $data = array();
    if ($res->num_rows > 0) {
        while ($row = $res->fetch_assoc()) {
            $list = new Lists();
            $list->id = $row['name'];
            $list->name = $row['name'];
            $list->url = $row['url'];
            $list->country = $row['country'];        
            array_push($data,$list);
        }
    } else {
        echo "没有数据";
    }

    //判断是否为跨域
    if (isset($_REQUEST['callback'])) {
        $callback = $_REQUEST['callback'];
        $str = json_encode($data);
        echo $callback.'('.$str.')';
    } else {
        echo json_encode($data);
    }

?>

前端代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    </body>
    <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.open('get','http://127.0.0.1:83/test/0513/cross_domain/jsonp.php',true);
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200) {
                var data = xhr.responseText;
                console.log(data);
                console.log(typeof data); 
                data = JSON.parse(data);
                console.log(data);
                console.log(typeof data);
            }
        }
    </script>
</html>

上面是用http协议请求的代码,浏览器显示如图:
这里写图片描述

前端代码2

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>

    </body>

    <script type="text/javascript">
        function ojson(data) {
            console.log(data);
        }
    </script>
    <script src="http://127.0.0.1:83/test/0513/cross_domain/jsonp.php?callback=ojson" type="text/javascript" charset="utf-8"></script>
</html>

这次用的是file协议,浏览器显示如图:
这里写图片描述
请求同一个api接口,file协议也能够获取到数据,只是要预定义一个全局的回调函数,并将函数名作为参数传给服务端。而服务端的代码则需要通过判断是否有回调来执行对应的操作。服务端返回的是一个回调函数的执行。

//isset可以用来判断是否为跨域
if (isset($_REQUEST['callback'])) {
    $callback = $_REQUEST['callback'];
    $str = json_encode($data);
    //输出用获取的回调函数操作的数据
    echo $callback.'('.$str.')';
} else {
    echo json_encode($data);
}
### JSONP 请求实现方法及原理 JSONP(JSON with Padding)是一种通过 `<script>` 标签的 `src` 属性来绕过浏览器同源策略限制的方法,从而实现在不同名之间传输数据的功能。其核心思想是利用 `<script>` 标签可以加载外部资源且不受同源策略约束这一特性。 #### 原理说明 当客户端发起一个请求时,由于 XMLHttpRequest 受限于同源策略无法直接访问其他上的资源,而 `<script>` 标签则可以通过设置 `src` 属性自由加载来自任何名下的 JavaScript 文件。因此,在 JSONP 中,客户端会在页面中动态创建一个 `<script>` 标签,并将其指向目标服务器的一个 URL 地址,同时附加一个回调函数名称作为查询参数[^1]。服务器接收到此请求后,会返回一段以指定回调函数包裹的数据形式的 JavaScript 代码。这段代码会被立即执行,进而调用预先定义好的回调函数并将所需数据传递进去[^2]。 #### 实现过程详解 以下是具体的操作流程: 1. **客户端准备阶段** 客户端先定义好用于接收响应数据的全局回调函数。 ```javascript function handleResponse(data) { console.log('Received data:', data); } ``` 2. **构建并插入 script 元素** 动态生成一个新的 `<script>` 元素,设定其 `src` 属性为目标接口地址加上必要的查询字符串(通常包含 callback 参数),最后将该元素添加至 DOM 结构中的合适位置(如 body 的子节点列表末端)。 ```javascript var script = document.createElement('script'); script.src = 'https://example.com/api?callback=handleResponse'; document.body.appendChild(script); ``` 3. **服务端配合处理** 当服务器接获带有特定 callback 名称字段的 HTTP 请求之后,应该按照约定格式构造回应内容——即将实际业务逻辑所产生的结果序列化成合法 JSON 字符串后再嵌套进由前述 callback 所指示的那个函数体内形成最终输出文本流送回前端展示层面上去渲染呈现出来供后续操作使用[^4]。 ```javascript // Example server-side pseudo-code (Node.js/Express-like syntax) app.get('/api', (req, res) => { const data = { key: 'value' }; const jsonResponse = JSON.stringify(data); const callbackFunctionName = req.query.callback || 'jsonpCallback'; res.send(`${callbackFunctionName}(${jsonResponse})`); }); ``` 以上便是整个基于 JSONP 技术完成的一次典型交互全过程描述总结概述完毕如下所示[^3]。 ```javascript // Client Side Code Summary function jsonpRequest(url, callbackName){ let scriptTag=document.createElement("script"); window[callbackName]=function(responseData){console.log(responseData);delete window[callbackName];}; scriptTag.src=`${url}&callback=${callbackName}`; document.head.append(scriptTag); } ``` ### 注意事项 尽管 JSONP 提供了一种简单有效的解决方案来进行通信,但它也存在一些固有的缺陷需要注意: - **安全性隐患**: 因为它依赖注入任意第三方站点提供的脚本来运行环境当中所以可能存在恶意代码攻击风险; - **仅支持 GET 方法**: 不允许像常规 AJAX 那样灵活运用多种类型的 HTTP Method 如 POST PUT DELETE 等等[^2].
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值