普歌-跨域及解決跨域(超詳細,面試官都誇贊)
前言:了解如何跨域前,首先了解什麼是跨域
同源政策
- 浏覽器的安全政策
- 協定名、域名、端口号完全一緻
跨域
違背同源政策就會産生跨域
解決跨域
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檔案,在項目的根目錄下,建立一個。在module.exports的dev對象下配置,也可以在configureWebpack: config=>{ … } 函數内判斷開發環境,然後config.devServer = { 配置資訊 }vue.config.js
配置資訊如下:
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共有,歡迎轉載,且在文章頁面明顯位置給出原文連結,未經作者同意必須保留此段聲明,否則保留追究法律責任的權利。