<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 6617字,需瀏覽 14分鐘

           ·

          2022-03-10 23:39

          3. 在服務(wù)端設(shè)置Access-Control-Allow-Credentials
          2. 在服務(wù)端設(shè)置Access-Control-Allow-Origin
          1. 在前端請求的時候設(shè)置request對象的屬性withCredentials為true;
          三、總結(jié)
          二、解決跨域攜帶cookie問題
          一. 搭建一個跨域請求的環(huán)境
          前言

          作者:Ethan01
          原文鏈接: https://juejin.cn/post/7066420545327218725?share_token=64606385-e1fa-497d-bdf3-dd753817542c

          作者:

          大廠技術(shù)  高級前端  Node進階

          點擊上方 程序員成長指北,關(guān)注公眾號

          回復(fù)1,加入高級Node交流群

          前言

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

          閱讀本文,你將學(xué)到:

          1.學(xué)會`withCredentials`屬性;
          2.學(xué)會`axios`配置`withCredentials`;
          3.學(xué)會設(shè)置`Access-Control-Allow-Origin`屬性;
          4.學(xué)會設(shè)置`Access-Control-Allow-Credentials`屬性;
          5.學(xué)會解決跨域請求攜帶源站cookie的問題;

          一. 搭建一個跨域請求的環(huán)境

          思路:

          1. 使用express搭建第一個服務(wù)A(http://localhost:8000),運行在8000端口上;

          2. A服務(wù)托管index.html(用于在前端頁面發(fā)送網(wǎng)絡(luò)請求)文件;

          3. A服務(wù)中寫一個處理請求的路由,加載index.html頁面時,種下cookie(這里種cookie為了在請求B服務(wù)時攜帶上);

          4. 使用express搭建第二個服務(wù)B(http://localhost:8003),運行在8003端口上;

          5. A服務(wù)托管的index.html頁面去請求B服務(wù),然后把cookie傳過去;

          先看下代碼結(jié)構(gòu),相對比較的簡單:

          A服務(wù)的代碼:

          // src/app1.js
          const express = require("express");
          const app = express();

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

          // 此接口是檢測`cookie`是否設(shè)置成功,如果設(shè)置成功的話,瀏覽器會自動攜帶上`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`中發(fā)起的請求,默認(rèn)的源就是`http://localhost:8000`
          // 然后再去請求`http://localhost:8003`就會出現(xiàn)跨域了
          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" />
          <meta http-equiv="X-UA-Compatible" content="IE=edge" />
          <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">發(fā)送同源請求</button>
          <button id="cross-button">發(fā)送跨域請求</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);
          });
          // 發(fā)送同域請求
          button.onclick = function () {
          axios.get("http://localhost:8000/user", {}).then((res) => {
          console.log(res);
          });
          };
          // 發(fā)送跨域請求
          crossButton.onclick = function () {
          axios({
          method: "get",
          url: "http://localhost:8003/anotherService",
          }).then((res) => {
          console.log(res);
          });
          };
          </script>
          </body>
          </html>

          B服務(wù)的代碼:

          // 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");
          });

          這個時候環(huán)境基本就搭建好了。

          二、解決跨域攜帶cookie問題

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

          npm install express -D
          node src/app1.js

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

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

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

          接下來刺激的畫面來了,我們點擊 發(fā)送跨域請求 按鈕,出現(xiàn)了跨域請求的報錯:

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

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

          什么是withCredentials?

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

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

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

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

          2. 在服務(wù)端設(shè)置Access-Control-Allow-Origin

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

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

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

          3. 在服務(wù)端設(shè)置Access-Control-Allow-Credentials

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

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

          再發(fā)送一個跨域請求:

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

          三、總結(jié)

          1. 前端請求時在request對象中配置"withCredentials": true;

          2. 服務(wù)端在responseheader中配置"Access-Control-Allow-Origin", "http://xxx:${port}";

          3. 服務(wù)端在responseheader中配置"Access-Control-Allow-Credentials", "true"

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

              
          Node 社群



          我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。



          如果你覺得這篇內(nèi)容對你有幫助,我想請你幫我2個小忙:

          1. 點個「在看」,讓更多人也能看到這篇文章
          2. 訂閱官方博客 www.inode.club 讓我們一起成長

          點贊和在看就是最大的支持??

          瀏覽 42
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲三级无码 | 国产精品一哟哟哟 | 97人妻精品 | 99精品国产麻豆99久久久久久 | 天天狠天天干 |