问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

前端中的jsonp如何解决跨域

创作时间:
作者:
@小白创作中心

前端中的jsonp如何解决跨域

引用
1
来源
1.
https://docs.pingcode.com/baike/2460258

JSONP(JSON with Padding)是一种“非正式”的跨域数据请求技术,其核心在于利用了浏览器对script标签的跨域加载能力。JSONP通过创建一个新的script标签,将请求发送到目标服务器,服务器返回的数据以JavaScript代码的形式包裹在一个回调函数中,浏览器执行这段代码,从而实现跨域请求。

一、JSONP的工作原理

JSONP(JSON with Padding)是一种“非正式”的跨域数据请求技术,其核心在于利用了浏览器对script标签的跨域加载能力。JSONP通过创建一个新的script标签,将请求发送到目标服务器,服务器返回的数据以JavaScript代码的形式包裹在一个回调函数中,浏览器执行这段代码,从而实现跨域请求。

1、动态创建script标签

在前端代码中,使用JavaScript动态创建一个script标签,并将其src属性设置为目标服务器的URL。浏览器会自动发送一个GET请求到该URL。

function fetchData(url, callback) {  
    const script = document.createElement('script');  
    script.src = `${url}?callback=${callback.name}`;  
    document.body.appendChild(script);  
}  

2、通过回调函数接收数据

服务器端需要返回的数据被包裹在一个回调函数中,前端通过定义这个回调函数来处理返回的数据。

function handleResponse(data) {  
    console.log(data);  
}  
// 发送请求  
fetchData('https://example.com/api', handleResponse);  

服务器返回的数据可能如下所示:

handleResponse({  
    "name": "John",  
    "age": 30  
});  

浏览器执行这段代码,从而调用了前端定义的回调函数,达到了跨域请求的目的。

二、JSONP的优缺点

1、优点

  • 简单易用:JSONP实现跨域请求的方式非常简单,只需动态创建一个script标签,并定义一个回调函数。
  • 兼容性好:JSONP不依赖于XMLHttpRequest对象,因此在一些老旧浏览器中也能正常工作。
  • 无需服务器配置:与CORS(跨域资源共享)不同,JSONP不需要服务器端进行额外配置,只需按照特定格式返回数据即可。

2、缺点

  • 仅支持GET请求:由于JSONP是通过script标签发送请求的,因此只能使用GET请求,无法发送POST请求。
  • 安全性问题:JSONP存在一定的安全风险,恶意的第三方服务器可以返回恶意代码,导致XSS(跨站脚本攻击)等安全问题。
  • 不支持复杂的数据类型:JSONP返回的数据必须是有效的JavaScript代码,无法直接返回复杂的数据结构。

三、JSONP的应用场景

由于JSONP的局限性,它通常用于以下场景:

  • 获取公共数据:例如从公共API获取天气信息、新闻数据等。这些数据通常是只读的,且安全性要求不高。
  • 无需身份验证的数据请求:由于JSONP存在安全性问题,因此不适合用于需要身份验证的请求。
  • 老旧浏览器的兼容性需求:在一些老旧浏览器中,CORS可能无法正常工作,此时可以考虑使用JSONP。

四、JSONP与CORS的比较

JSONP和CORS都是解决跨域请求问题的常用方法,但它们在实现方式、适用场景和安全性方面有所不同。

1、实现方式

JSONP通过动态创建script标签发送GET请求,服务器返回的数据以JavaScript代码的形式包裹在回调函数中。CORS通过设置HTTP头部,允许浏览器跨域访问资源,支持GET、POST等多种HTTP方法。

2、适用场景

JSONP适用于获取公共数据、无需身份验证的数据请求,且在老旧浏览器中有良好的兼容性。CORS适用于需要更高安全性、支持多种HTTP方法的跨域请求,且需要服务器端配置支持。

3、安全性

JSONP存在一定的安全风险,恶意的第三方服务器可以返回恶意代码,导致XSS等安全问题。CORS通过设置HTTP头部,允许浏览器安全地跨域访问资源,安全性相对较高。

五、JSONP的实现步骤

1、前端代码

前端代码主要包括动态创建script标签、定义回调函数两个部分。

function fetchData(url, callback) {  
    const script = document.createElement('script');  
    script.src = `${url}?callback=${callback.name}`;  
    document.body.appendChild(script);  
}  
function handleResponse(data) {  
    console.log(data);  
}  
// 发送请求  
fetchData('https://example.com/api', handleResponse);  

2、服务器端代码

服务器端需要按照特定格式返回数据,包裹在回调函数中。例如,使用Node.js和Express框架实现一个简单的服务器:

const express = require('express');  
const app = express();  
app.get('/api', (req, res) => {  
    const callback = req.query.callback;  
    const data = {  
        "name": "John",  
        "age": 30  
    };  
    res.send(`${callback}(${JSON.stringify(data)})`);  
});  
app.listen(3000, () => {  
    console.log('Server is running on port 3000');  
});  

六、JSONP的实际案例

1、获取天气信息

假设我们需要从一个公共API获取天气信息,可以使用JSONP实现跨域请求。

前端代码:

function fetchWeather(city) {  
    function handleWeatherResponse(data) {  
        console.log(`The weather in ${city} is ${data.weather}`);  
    }  
    const url = `https://api.weather.com/v1/city/${city}`;  
    fetchData(url, handleWeatherResponse);  
}  
// 获取北京的天气信息  
fetchWeather('Beijing');  

服务器端代码:

const express = require('express');  
const app = express();  
app.get('/v1/city/:city', (req, res) => {  
    const callback = req.query.callback;  
    const city = req.params.city;  
    const data = {  
        "city": city,  
        "weather": "Sunny"  
    };  
    res.send(`${callback}(${JSON.stringify(data)})`);  
});  
app.listen(3000, () => {  
    console.log('Server is running on port 3000');  
});  

2、获取新闻数据

假设我们需要从一个公共API获取新闻数据,也可以使用JSONP实现跨域请求。

前端代码:

function fetchNews() {  
    function handleNewsResponse(data) {  
        console.log(`Latest news: ${data.headline}`);  
    }  
    const url = 'https://api.news.com/v1/latest';  
    fetchData(url, handleNewsResponse);  
}  
// 获取最新新闻  
fetchNews();  

服务器端代码:

const express = require('express');  
const app = express();  
app.get('/v1/latest', (req, res) => {  
    const callback = req.query.callback;  
    const data = {  
        "headline": "Breaking News: JSONP is awesome!"  
    };  
    res.send(`${callback}(${JSON.stringify(data)})`);  
});  
app.listen(3000, () => {  
    console.log('Server is running on port 3000');  
});  

七、替代方案:CORS

尽管JSONP在某些场景中仍然有效,但由于其局限性和安全问题,现代Web开发中更常用的是CORS(跨域资源共享)。

1、CORS的基本原理

CORS通过设置HTTP头部,允许浏览器跨域访问资源。服务器端需要配置允许的来源、方法和头部信息。

2、前端代码

与普通的AJAX请求类似,使用XMLHttpRequest或Fetch API发送请求。

fetch('https://api.example.com/data', {  
    method: 'GET',  
    headers: {  
        'Content-Type': 'application/json'  
    }  
})  
.then(response => response.json())  
.then(data => console.log(data))  
.catch(error => console.error('Error:', error));  

3、服务器端代码

服务器端需要配置CORS头部信息。例如,使用Node.js和Express框架:

const express = require('express');  
const app = express();  
app.use((req, res, next) => {  
    res.header('Access-Control-Allow-Origin', '*');  
    res.header('Access-Control-Allow-Methods', 'GET,POST');  
    res.header('Access-Control-Allow-Headers', 'Content-Type');  
    next();  
});  
app.get('/data', (req, res) => {  
    const data = {  
        "message": "Hello, world!"  
    };  
    res.json(data);  
});  
app.listen(3000, () => {  
    console.log('Server is running on port 3000');  
});  

八、总结

JSONP通过动态创建script标签、通过回调函数接收数据、实现跨域请求,具有简单易用、兼容性好的优点,但也存在安全性问题、仅支持GET请求等局限性。在现代Web开发中,CORS更常用,因为它支持多种HTTP方法、更高的安全性和更丰富的功能。

无论选择JSONP还是CORS,都需要根据具体的应用场景和需求进行权衡。在需要获取公共数据、无需身份验证的场景下,JSONP仍然是一个有效的解决方案。然而,在需要更高安全性、支持多种HTTP方法的场景下,CORS则更为合适。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号