产生跨域的情况:
请求的地址只要协议、域名、端口三者之一或以上和后端地址不一致,就会导致跨域的产生。
解决跨域的常用三种方式:
- JSONP
- CORS
- Proxy
JSONP:
利用SCRIPT标签不存在域的限制实现出跨域请求(弊端:只能是GET请求 / 不安全,只要服务器支持,谁都可以调用) ,callback必须是一个全局上下文中的函数(防止不是全局的函数,我们需要把这个函数防止到全局上)
//前端代码
function jsonp(url = "", callback) {
let script;
// 把传递的回调函数挂载到全局上
let name = `jsonp${new Date().getTime()}`;
window[name] = data => {
// 从服务器获取到了结果
document.body.removeChild(script);
delete window[name];
callback && callback(data);
};
// 处理URL
url += `${url.includes('?')?'&':'?'}callback=${name}`;
// 发送请求
script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}
jsonp('http://127.0.0.1:1001/list?lx=1', result => {
console.log(result);
});
jsonp('https://matchweb.sports.qq.com/matchUnion/cateColumns?from=pc', result => {
console.log(result);
});
后端代码(node举例):
app.get('/list', (req, res) => {
// req.query 问号传递的参数信息
// callback存储的是一个函数名(客户端全局的)
let {
callback
} = req.query;
// 准备返回的数据
let result = {
code: 0,
data: [10, 20]
};
let str = `${callback}(${JSON.stringify(result)})`;
res.send(str);
});
CORS:
/* CORS:服务器端设置(设置允许源) */
app.use((req, res, next) => {
// 设置允许源
// * 允许所有源(不安全/不能携带资源凭证)
// 设置单一源(安全/也可以携带资源凭证/只能是单一一个源)
// 可以动态设置多个源:每一次请求都会走这个中间件,我们首先设置一个白名单,如果当前客户端请求的源在白名单中,我们把Allow-Origin动态设置为当前这个源
/* let safeList = [
"http://127.0.0.1:5500"
]; */
res.header("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
res.header("Access-Control-Allow-Credentials", true);
/* res.header("Access-Control-Allow-Headers", "Content-Type,....");
res.header("Access-Control-Allow-Methods", "GET,..."); */
// 试探请求:在CORS跨域请求中,首先浏览器会自己发送一个试探请求,验证是否可以和服务器跨域通信,服务器返回200,则浏览器继续发送真实的请求
req.method === 'OPTIONS' ? res.send('CURRENT SERVICES SUPPORT CROSS DOMAIN REQUESTS!') : next();
});
Proxy:一般在webpack中配置,这种方式只能在开发环境中配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/main.js',
output: {
filename: 'main.[hash].min.js',
path: path.resolve(__dirname, 'build')
},
devServer: {
port: '3000',
compress: true,
open: true,
hot: true,
proxy: {
'/': {
target: 'http://127.0.0.1:3001',
changeOrigin: true
}
}
},
// 配置WEBPACK的插件
plugins: [
new HtmlWebpackPlugin({
template: `./public/index.html`,
filename: `index.html`
})
]
};
但是在实际上线的时候需要在nginx中设置反向代理