Loading... ## 前言 最近博主在开发翰络云工具的ip查询工具([https://www.hanloth.cn/tool/ip-query-master](https://www.hanloth.cn/tool/ip-query-master)),并且发了一篇文章来总结和展示所有用到的ip查询接口([https://ivan.hanloth.cn/archives/649/](https://ivan.hanloth.cn/archives/649/))。但是开发过程中发现一些ip接口的同源策略不允许跨域(哭死),为了能够使用这些接口,博主不得不再一次仔细研究前端的同源策略,并总结了一些绕过该策略的方法,同时附上一些容易混淆的点的辨析。 ## 同源策略是什么? 同源策略(Same-Origin Policy,简称 SOP)是一种安全机制,用于限制不同源(即不同域名、协议或端口)之间的脚本在浏览器中的交互。具体来说,同源策略规定,只有当网页与所请求的资源具有相同的来源时,才能相互访问其数据。这一策略主要用于防止跨站请求伪造(CSRF)和跨站脚本攻击(XSS)等安全威胁。 ## 为什么要有同源策略? 同源策略的主要目的是保护用户数据的安全,防止恶意网站在未经用户同意的情况下访问其他网站的敏感数据。例如,用户登录了银行网站,同时打开了一个恶意网站。如果没有同源策略,恶意网站可能会通过脚本访问银行网站的敏感信息,从而进行恶意操作。 ## 常用的绕过同源策略的办法 虽然同源策略是为了安全而设计的,但在某些情况下需要跨源访问数据,这时候就需要一些技术来绕过同源策略。常用的方法包括: 1. **JSONP** (JSON with Padding) 2. **CORS** (Cross-Origin Resource Sharing) 3. **代理服务器** 4. **window.postMessage** 5. **跨域资源共享 (CORS)** 6. **WebSockets** ## 什么是JSONP? JSONP(JSON with Padding)是一种跨域请求数据的方法。它利用了 `<script>` 标签不受同源策略限制的特点,通过动态创建 `<script>` 标签来发送跨域请求,并将服务器返回的数据作为 JavaScript 函数的参数来执行。 ## JSONP的原理 JSONP 的基本原理是利用 `<script>` 标签可以跨域加载脚本的特性。具体步骤如下: 1. 客户端创建一个带有回调函数名的 `<script>` 标签,并将其插入 HTML 中。 2. 服务器接收到请求后,将数据封装在一个回调函数中,并返回给客户端。 3. 客户端执行返回的脚本,调用预先定义的回调函数处理数据。 ## JSON和JSONP的区别 * **JSON** :是一种数据格式,主要用于在服务器和客户端之间交换数据,不能跨域请求。 * **JSONP** :是一种数据传输机制,通过动态创建 `<script>` 标签来绕过同源策略,允许跨域请求数据。 ## 如何使用JSONP ### 客户端 使用 JSONP 的步骤如下: 1. 在客户端定义一个回调函数。 2. 动态创建一个 `<script>` 标签,设置其 `src` 属性为请求的 URL,并带上回调函数名。 3. 服务器接收请求,生成 JSON 数据,并将其封装在回调函数中返回。 4. 客户端接收到返回的脚本后,执行回调函数,处理数据。 ```javascript // 客户端代码 function handleResponse(data) { console.log(data); } const script = document.createElement('script'); script.src = 'https://example.com/data?callback=handleResponse'; document.body.appendChild(script); ``` ### 服务端 当客户端发送一个 JSONP 请求时,服务端需要对请求进行处理,并生成一个包含回调函数的响应。具体步骤如下: 1. **解析回调函数名** :服务端从请求的 URL 参数中解析出回调函数名。 2. **生成 JSON 数据** :服务端生成需要返回的 JSON 数据。 3. **封装 JSON 数据** :将生成的 JSON 数据封装在回调函数中。 4. **返回响应** :将封装后的数据作为响应发送回客户端。 ```php <?php // 获取回调函数名 $callback = isset($_GET['callback']) ? $_GET['callback'] : 'callback'; // 生成 JSON 数据 $data = [ 'status' => 'success', 'message' => 'This is a JSONP response', 'data' => [ 'id' => 1, 'name' => 'Example' ] ]; // 将数据封装在回调函数中 $response = $callback . '(' . json_encode($data) . ');'; // 设置响应头为 JavaScript MIME 类型 header('Content-Type: application/javascript'); // 返回响应 echo $response; ?> ``` **代码解释:** * **获取回调函数名** :通过 `$_GET['callback']` 获取客户端传递的回调函数名,如果没有传递,则使用默认值 `'callback'`。 * **生成 JSON 数据** :创建一个包含状态、消息和数据的关联数组,并将其转换为 JSON 格式。 * **封装 JSON 数据** :将 JSON 数据封装在回调函数中,形成类似 `handleResponse({...})` 的字符串。 * **设置响应头** :将响应头设置为 `application/javascript`,告知客户端这是 JavaScript 代码。 * **返回响应** :输出封装好的响应,客户端会执行返回的脚本,调用回调函数处理数据。 ## JSONP的局限性 虽然 JSONP 提供了一种简单的跨域数据请求方法,但它也有一些局限性: 1. **仅支持GET请求** :由于 JSONP 是通过 `<script>` 标签实现的,只能使用 GET 请求,无法使用 POST 等其他 HTTP 方法。 2. **安全风险** :因为 JSONP 执行的是返回的 JavaScript 代码,如果服务器不可信,可能会引入恶意代码,导致安全问题。 3. **数据格式限制** :JSONP 只能处理 JSON 数据,而不能处理其他格式的数据。 4. **依赖回调函数名** :JSONP 请求需要传递回调函数名,增加了代码的复杂性,且需要服务端的支持适配。 Last modification:June 10, 2024 © Allow specification reprint Support Appreciate the author AliPayWeChat Like 如果觉得我的文章对你有用,请随意赞赏