成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官 -- 跨域請求如何攜帶 Cookie ?

開發 前端
(常規的面試套路,一般都會順著你的回答往深了問)由于之前的項目都是同源的,不牽涉跨域訪問,所以一時沒有回答出來,后來研究了下,所以有了這篇文章。

前言

最近在參加面試找工作,陸陸續續的面了兩三家。其中面試官問到了一個問題:如何解決跨域問題?我巴巴拉拉的一頓說,大概了說了四種方法,然后面試官緊接著又問:那跨域請求怎么攜帶cookie呢?(常規的面試套路,一般都會順著你的回答往深了問)由于之前的項目都是同源的,不牽涉跨域訪問,所以一時沒有回答出來,后來研究了下,所以有了這篇文章。

閱讀本文,你將學到:

1.學會`withCredentials`屬性;

2.學會`axios`配置`withCredentials`;

3.學會設置`Access-Control-Allow-Origin`屬性;

4.學會設置`Access-Control-Allow-Credentials`屬性;

5.學會解決跨域請求攜帶源站cookie的問題

一. 搭建一個跨域請求的環境

思路:

  1.    使用express搭建第一個服務A(http://localhost:8000),運行在8000端口上;
  2.    A服務托管index.html(用于在前端頁面發送網絡請求)文件;
  3.    在A服務中寫一個處理請求的路由,加載index.html頁面時,種下cookie(這里種cookie為了在請求B服務時攜帶上);
  4. 使用express搭建第二個服務B(http://localhost:8003),運行在8003端口上;
  5. 在A服務托管的index.html頁面去請求B服務,然后把cookie傳過去;

先看下代碼結構,相對比較的簡單:

A服務的代碼:

// src/app1.js
const express = require("express");
const app = express();
// `index.html` 加載時會請求login接口
// 設置`cookie`
app.get("/login", (req, res) => {
res.cookie("user", "jay", { maxAge: 2000000, httpOnly: true });
res.json({ code: 0, message: "登錄成功" });
});

// 此接口是檢測`cookie`是否設置成功,如果設置成功的話,瀏覽器會自動攜帶上`cookie`
app.get("/user", (req, res) => {
// req.headers.cookie: user=jay
const user = req.headers.cookie.split("=")[1];
res.json({ code: 0, user });
});

// 托管`index.html`頁面
// 這樣的話在`index.html`中發起的請求,默認的源就是`http://localhost:8000`
// 然后再去請求`http://localhost:8003`就會出現跨域了
app.use("/static", express.static("public"));
app.listen("8000", () => {
console.log("app1 running at port 8000");
});

index.html的代碼:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<met
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2>this is index.html at port 8000</h2>
<button id="button">發送同源請求</button>
<button id="cross-button">發送跨域請求</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
const button = document.querySelector("#button");
const crossButton = document.querySelector("#cross-button");
axios.get("http://localhost:8000/login", {}).then((res) => {
console.log(res);
});
// 發送同域請求
button.onclick = function () {
axios.get("http://localhost:8000/user", {}).then((res) => {
console.log(res);
});
};
// 發送跨域請求
crossButton.onclick = function () {
axios({
method: "get",
url: "http://localhost:8003/anotherService",
}).then((res) => {
console.log(res);
});
};
</script>
</body>
</html>

B服務的代碼:

// src/app2.js
const express = require("express");
const app = express();
// 定義一個接口,index.html頁面請求這個接口就是跨域(因為端口不同)
app.get("/anotherService", (req, res) => {
res.json({ code: 0, msg: "這是8003端口返回的" });
});
app.listen("8003", () => {
console.log("app2 running at port 8003");
});

這個時候環境基本就搭建好了。

二、解決跨域攜帶cookie問題

首先我們先在A服務的index.html頁面中得到一個cookie,運行A服務:

npm install express -D
node src/app1.js

然后打開http://localhost:8000/static/index.html: 沒有問題的話,頁面長這樣:

這個時候F12打開控制臺:可以看到發送了一個login請求,并且設置了cookie,也可以選擇瀏覽器控制臺的Application頁簽,選中cookie,可以看到cookie的信息:

然后我們點擊頁面上的發送同源請求按鈕,可以看到發送了一個user請求,并且已經攜帶上了cookie:

接下來刺激的畫面來了,我們點擊 發送跨域請求 按鈕,出現了跨域請求的報錯:

重點:接下來開始解決跨域攜帶cookie問題:

1. 在前端請求的時候設置request對象的屬性withCredentials為true;

什么是withCredentials?

XMLHttpRequest.withCredentials 屬性是一個Boolean類型,它指示了是否該使用類似cookies,authorization headers(頭部授權)或者TLS客戶端證書這一類資格證書來創建一個跨站點訪問控制(cross-site Access-Control)請求。在同一個站點下使用withCredentials屬性是無效的。

如果在發送來自其他域的XMLHttpRequest請求之前,未設置withCredentials 為true,那么就不能為它自己的域設置cookie值。而通過設置withCredentials 為true獲得的第三方cookies,將會依舊享受同源策略,因此不能被通過document.cookie或者從頭部相應請求的腳本等訪問。

// 修改跨域請求的代碼
crossButton.onclick = function () {
axios({
withCredentials: true, // ++ 新增
method: "get",
url: "http://localhost:8003/anotherService",
}).then((res) => {
console.log(res);
});
};

這個時候再去發送一個跨域請求,你會發現依舊報錯,但是我們仔細看下報錯,意思是需要設置header的Access-Control-Allow-Origin屬性:

2. 在服務端設置Access-Control-Allow-Origin

我們修改B(app2.js)服務的代碼:

// 在所有路由前增加,可以攔截所有請求
app.all("*", (req, res, next) => {
res.header("Access-Control-Allow-Origin", "http://localhost:8000");
next();
});

修改完之后再次發送一個跨域請求,你會發現,又報錯了(接近崩潰),但是跟之前報的錯不一樣了,意思大概就是Access-Control-Allow-Credentials這個屬性應該設置為true,但是顯示得到的是個'':

3. 在服務端設置Access-Control-Allow-Credentials

再次修改B服務的代碼(每次修改后需要重新運行):

// 在所有路由前增加,可以攔截所有請求
app.all("*", (req, res, next) => {
res.header("Access-Control-Allow-Origin", "http://localhost:8000");
res.header("Access-Control-Allow-Credentials", "true"); // ++ 新增
next();
});

再發送一個跨域請求:

可以看到,這個跨域請求已經請求成功并且返回數據了!而且也攜帶了A服務的cookie,這個時候已經大功告成了。

三、總結

  1. 前端請求時在request對象中配置"withCredentials": true;
  2. 服務端在response的header中配置"Access-Control-Allow-Origin", "http://xxx:${port}";
  3. 服務端在response的header中配置"Access-Control-Allow-Credentials", "true"

如果看完這篇文章能夠幫助到你,請給個贊哦!

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2022-03-21 07:35:34

處理方式跨域

2015-08-13 10:29:12

面試面試官

2022-02-08 08:14:07

Context數據線程

2011-04-18 14:23:37

javascriptHTML

2023-02-16 08:10:40

死鎖線程

2021-01-18 05:13:04

TomcatHttp

2022-01-18 09:02:45

請求前端代碼

2024-10-16 15:01:20

2024-01-10 15:27:58

SessionCookieWeb 應用

2010-08-12 16:28:35

面試官

2024-04-03 00:00:00

Redis集群代碼

2024-09-11 22:51:19

線程通訊Object

2021-07-06 07:08:18

管控數據數倉

2025-03-17 00:00:00

2023-11-20 10:09:59

2024-02-20 14:10:55

系統緩存冗余

2024-03-18 14:06:00

停機Spring服務器

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2021-03-16 22:25:06

作用域鏈作用域JavaScript

2020-06-12 15:50:56

options前端服務器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 女人夜夜春 | 综合久久久久 | 中国av在线免费观看 | 欧美日韩在线观看视频网站 | 亚洲视频免费在线观看 | 日韩精品三区 | 精品久久久久久久久久久下田 | 久久精品1 | 国产在线a | 在线不卡视频 | 国产精品久久亚洲7777 | 国产精品久久国产精品久久 | 成人区精品一区二区婷婷 | 亚洲一区中文字幕在线观看 | 欧美色综合天天久久综合精品 | 九九热国产精品视频 | 国产精品日韩欧美一区二区三区 | 欧美黄色小视频 | 日日综合| 91精品久久久久久久久中文字幕 | 黄a在线观看 | 久操亚洲| 成人免费观看男女羞羞视频 | 在线a视频网站 | 国产区在线观看 | 久久精品男人的天堂 | 欧美自拍一区 | 欧美三级成人理伦 | 午夜精品久久久久久久久久久久久 | 日本一区二区三区视频在线 | 天天躁日日躁狠狠躁白人 | 成人亚洲精品久久久久软件 | 久久久久亚洲 | 91精品国产综合久久国产大片 | 国产亚洲精品区 | 日本三级日产三级国产三级 | 一区二区三区视频播放 | 久草综合在线视频 | 99精品国产成人一区二区 | 久久精品国产一区二区三区不卡 | 中文字幕在线视频精品 |