普歌-跨域及解决跨域(超详细,面试官都夸赞)
前言:了解如何跨域前,首先了解什么是跨域
- 同源策略
- 浏览器的安全策略
- 协议名、域名、端口号完全一致- 跨域
违背同源策略就会产生跨域- 解决跨域
jsonp(前端设置和后端设置) \ cors(后端设置) \服务器代理(后端设置)…
当时3月底面试快手是提起这个怎么解决跨域时,说的面试都称,说的很详细,我相信你即使没实践过也能很快上手(原话)~~~~但最后挂在二面了😂😂😂
用jsonp解决跨域(前后端配合设置)
jsonp原理是因为script标签是没有同源策略限制,可以跨域的,用动态生成的script标签;限制的话只能发送get请求
封装jsonp函数
//options中又很多参数
function jsonp(options) {
//动态创建script标签
var script = document.createElement("script"); //拼接字符串的变量
//进行url参数的拼接,形如name=gl&age=20
var params = "";
for (var attr in options.data) {
params += "&" + attr + "=" + options.data[attr];
}
//myJsonp0213212,生成一个函数名(要通过callback传递给后端)
var fnName = "myJsonp" + Math.random().toString().replace(".", "");
//我们要想办法将它变成全局函数
//(变成全局函数的目的在于后端返回的参数形式是->func({data...})前端能自动执行得到真正的参数)
window[fnName] = options.success;
//拼接callback以及参数给后端
//为script标签添加src属性
script.src = options.url + "?callback=" + fnName + params;
//将script标签追加到页面中
document.body.appendChild(script);
//为script标签添加onload事件,在调用完就移除script,不会增加一些多余的标签
script.onload = function () {
document.body.removeChild(script);
};
}
进行测试
<body>
<button id="btn1">点我发送请求</button> <button id="btn2">
点我发送请求
</button>
<script type="text/javascript">
//获取按钮
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2"); //为按钮添加点击事件
btn1.onclick = function () {
jsonp({
//请求地址
url: "http://localhost:3001/better",
data: {
name: "lisi",
age: 30,
},
success: function (data) {
console.log(123);
console.log(data);
},
});
};
btn2.onclick = function () {
jsonp({
//请求地址
url: "http://localhost:3001/better",
success: function (data) {
console.log(456789);
console.log(data);
},
});
};
function jsonp(options) {
//动态创建script标签
var script = document.createElement("script"); //拼接字符串的变量
//
var params = "";
for (var attr in options.data) {
params += "&" + attr + "=" + options.data[attr];
}
//myJsonp0213212
var fnName = "myJsonp" + Math.random().toString().replace(".", "");
//它已经不是一个全局函数了
//我们要想办法将它变成全局函数
window[fnName] = options.success;
//拼接callback以及参数给后端
//为script标签添加src属性
script.src = options.url + "?callback=" + fnName + params;
//将script标签追加到页面中
document.body.appendChild(script);
//为script标签添加onload事件,在调用完就移除script,不会增加一些多余的标签
script.onload = function () {
document.body.removeChild(script);
};
}
</script>
</body>
我之前也发现百度也使用jsonp发送请求
CROS跨域(CORS是后端的事)
- 客户端(项目中一般都用axios发送请求)
- 客户端封装axios
import axios from "axios";
import qs from "qs";
axios.defaults.baseURL = "http://127.0.0.1:3000";
axios.defaults.timeout = 10000;
//withCredentials 这个是向服务器跨域发送请求允不允许携带资源凭证(cookie)
axios.defaults.withCredentials = true;
/*
* 设置请求传递数据的格式(看服务器要求什么格式)
* x-www-form-urlencoded
*/
axios.defaults.headers["Content-Type"] =
"application/x-www-form-urlencoded";
axios.defaults.transformRequest = (data) => qs.stringify(data);
//以上还可以写成对象形式
/* const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
timeout: 10000 // request timeout
})*/
/*
* 设置请求拦截器
* TOKEN校验(JWT):接收服务器返回的token,存储到vuex/本地存储中,每一次向服务器发请求,我们应该把token带上
*/
axios.interceptors.request.use(
(config) => {
let token = localStorage.getItem("token");
token && (config.headers.Authorization = token);
return config;
},
(error) => {
return Promise.reject(error);
}
);
/*
* 响应拦截器
*/
axios.interceptors.response.use(
(response) => {
return response.data;
},
(error) => {}
);
export default axios;
Node服务端设置跨域
// 这里是node中的做法
app.use((req, res, next) => {
// 允许哪些源访问,到项目中应用的话可以给一个*(就是所有源),或者填写某个具体的域
res.header("Access-Control-Allow-Origin", "*");
// 允不允许客户端发送资源凭证 Credentials
res.header("Access-Control-Allow-Credentials", true);
// 允许发送哪些请求头
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length,Authorization, Accept,X-Requested-With");
//允许发送哪些请求
res.header( "Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS,HEAD");
// 发送正常请求(post/get等)前会提起发送OPTIONS试探性请求,看看能不能连上服务器
req.method === "OPTIONS"? res.send("CURRENT SERVICES SUPPORT CROSS DOMAIN REQUESTS!"): next();
});
基于http/https proxy实现跨域请求(开发环境)
-
配置proxy只有在开发环境中起作用,因为webpack只有在开发时用到
-
第一,配置webpack代理
打开 webpack 配置文件,进入开发环境下配置。在module.exports的dev对象下。 -
如果是 vue cli 3 ,刚进入
vue.config.js
。如果没有vue.config.js文件,在项目的根目录下,创建一个。在module.exports的dev对象下配置,也可以在configureWebpack: config=>{ … } 函数内判断开发环境,然后config.devServer = { 配置信息 }
配置信息如下:
module.exports = {
devServer: {
proxy: {
//定义请求的基础URL, 方便跨域请求时使用
"/api": {
// 目标服务器地址
target: "http://172.16.1.18:8769",
// 开启代理服务器,
changeOrigin: true,
// 将 请求地址前缀 /api 替换为 空的,
pathRewrite: {
"^/api": ""
},
secure: false
}
}
}
}
参数解读:
“/api”: 指接口调用时,遇到接口路径为 api 时,则代理转发到 target 的配置url上
target: 开发环境调用的接口地址
changeOrigin:改变源到url,在虚拟主机上很有用
pathRewrite:是指服务器把接口中api去掉,以免api这几个字母加入到接口地址中
secure: false, // 接受 运行在 https 上的服务
生产环境中要用nginx反向代理(生产环境)
nginx配置反向代理
还有一个iframe跨域,只不过我没实战过…
iframe跨域
OVER,get到的小伙伴给个三连呗~~~
更多推荐:wantLG的《普歌-页面优化之实现图片懒加载+节流(面试重点)》
- 作者:wantLG
- 本文源自:wantLG的《普歌-多种跨域方式以及解决跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)》
- 本文版权归作者和CSDN共有,欢迎转载,且在文章页面明显位置给出原文链接,未经作者同意必须保留此段声明,否则保留追究法律责任的权利。