面试题答案
一键面试JSONP原理分析
- 原理:
- JSONP利用了
<script>
标签没有跨域限制的特性。当在页面中动态创建一个<script>
标签,并将其src
属性设置为跨域的API地址时,浏览器会向该地址发起请求。 - 服务端返回一段JavaScript代码,这段代码以调用页面中预先定义好的函数的形式,将数据作为参数传递过来。例如,假设页面定义了函数
callback
,服务端返回callback({data: '一些数据'})
,这样就实现了跨域获取数据。
- JSONP利用了
JSONP局限性
- 只支持GET请求:因为
<script>
标签只能发起GET请求,无法像XMLHttpRequest
那样支持POST等其他请求方法,在需要提交大量数据等场景下无法满足需求。 - 存在安全风险:由于JSONP是通过动态插入
<script>
标签执行返回的JavaScript代码,如果服务端被劫持,恶意攻击者可以返回恶意脚本,导致XSS(跨站脚本攻击)等安全问题。 - 同源策略限制:JSONP只能绕过浏览器的同源策略限制进行数据获取,但对于一些涉及到跨域的复杂操作,如跨域访问Cookie、跨域的XMLHttpRequest等,JSONP无法解决。
优化或替代方案
- CORS(跨域资源共享):
- 优势:
- 支持多种请求方法,如GET、POST、PUT、DELETE等,能够满足不同场景下的接口需求。
- 安全性高,通过设置响应头来控制哪些来源可以访问资源,减少了XSS等安全风险。
- 实现思路:
- 服务端配置:在服务端设置响应头,例如在Node.js的Express框架中,可以使用
cors
中间件。首先安装cors
:npm install cors
,然后在代码中引入并使用:
- 服务端配置:在服务端设置响应头,例如在Node.js的Express框架中,可以使用
- 优势:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
// 这里开始定义路由等
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
- **客户端无需特殊处理**:在Vue项目中,使用 `axios` 等请求库时,只要服务端配置好CORS,客户端像请求同源接口一样发送请求即可。例如:
import axios from 'axios';
axios.get('http://otherdomain.com/api/data').then(response => {
console.log(response.data);
});
- 代理服务器:
- 优势:
- 可以对请求进行更多的控制和处理,如请求转发、请求头修改等。
- 对于一些复杂的跨域场景,代理服务器可以起到中间桥梁的作用,同时隐藏真实的后端接口地址,增加安全性。
- 实现思路:
- 搭建代理服务器:可以使用Node.js搭建一个简单的代理服务器。例如,使用
http-proxy-middleware
库。首先安装:npm install http-proxy-middleware
。假设要代理http://targetdomain.com/api
接口,在Node.js代码中:
- 搭建代理服务器:可以使用Node.js搭建一个简单的代理服务器。例如,使用
- 优势:
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use('/api', createProxyMiddleware({
target: 'http://targetdomain.com',
changeOrigin: true
}));
app.listen(4000, () => {
console.log('Proxy server is running on port 4000');
});
- **Vue项目配置**:在Vue项目的 `vue.config.js` 中配置代理,这样所有以 `/api` 开头的请求都会被代理到代理服务器:
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:4000',
changeOrigin: true
}
}
}
};
这样在Vue项目中请求 /api/data
时,实际上会通过代理服务器转发到 http://targetdomain.com/api/data
。