Cookie 會話身份驗證是如何工作的?

在 Web 應用程序中,Cookie-Session 是一種標準的身份驗證方法。餅乾,也被稱爲“sweet cookies”。類型爲“小文本文件”,是指一些網站爲了識別用戶身份而存儲在客戶端的數據。Session的主要功能是通過服務器記錄用戶的狀態。

 

在典型的在線購物場景中,用戶瀏覽多個頁面並將一些商品添加到購物車。儘管如此,系統並不知道是哪個用戶進行了操作,因爲HTTP協議是無狀態的,所以服務端需要爲不同的用戶創建相應的Session來識別和跟蹤這個用戶。在服務器端保存Session的方式有很多種,比如保存到內存、數據庫或者文件中。

我們看一下Cookie-Session的認證過程:

 

這是一個典型的 HTTP 客戶端(瀏覽器)和 HTTP 服務器對話,服務器運行在同一臺計算機(本地主機)上,包含以下步驟。

  1. 用戶訪問登錄頁面後,輸入相應的用戶名和密碼進行登錄操作。
  2. 在客戶端發起登錄請求。一般在瀏覽器環境下,可以通過AJAX或者Form發起登錄請求。
  3. 當服務器通過認證時,將爲認證成功的用戶創建一個Session,並存儲Session信息。之後服務器會通過HTTP響應頭來設置SessionId,即HTTP響應頭中會包含 的響應頭信息Set-Cookie。如果認證失敗,則提示用戶進行相關操作。
  4. 認證成功後,用戶訪問頁面獲取用戶信息,此時客戶端會在HTTP請求頭中攜帶cookie信息。
  5. 服務端接收到客戶端發起的請求,獲取cookie中存儲的SessionId來驗證用戶身份,驗證通過後返回相應信息。

下面我將使用Koa來介紹Cookie-Session的認證過程。首先我們來定義首頁的路由:

// router.js
路由器。get ( "/" , async (     ctx ) => {
 if (ctx.session.user ) { const { userName } = ctx.session.user ; ctx.body = ` < h1 > Cookie         /Session Authentication</h1>       你好, ${userName}         <div>           <a href="./getUserInfo">用戶信息</a>           <a href="./logout">註銷</a>         </div>         ` ;   } else {     ctx.
   









“登錄”);
}
});

在上面的代碼中,我們首先會判斷當前用戶是否已經登錄到web應用中。如果已登錄,將顯示與當前用戶對應的問候消息。如果沒有登錄,會跳轉到登錄頁面,所以我們需要註冊登錄頁面的路由:

// router.js
路由器。get ( "/login" , ( ctx     ) => {
 if (ctx.session.user ) { ctx.redirect ( " /" );   } else { ctx.body     = ` <form method = "     post" action="/ login">       <p><label>用戶名</label><input type="text" name="username" /></p>       <p><label>密碼</label><input type="password" name="密碼" /></p>       <button type="

當未登錄的用戶在瀏覽器中訪問
http://localhost:3000/login地址時,會顯示如下用戶登錄表單:

 

當用戶輸入用戶名和密碼並點擊登錄按鈕時,瀏覽器會發起POST請求並調用/loginAPI。對應的/login路由處理邏輯如下:

// router.js
路由器。post ( "/login" , async (ctx) => {
 try {
   const loginData = ctx.request . body ; const
  { username, password } = loginData;
   if (username === "bytefer" && password === "123 " ) {
     ctx. session . user = { userName : "bytefer" , userId : "007" };
     ctx. response . redirect ( "/"
  }否則{
     ctx。body = {代碼:0,消息:“登錄失敗!” };
  }
} catch (err) {
   throw  new  Error ( "登錄錯誤" );
}
});

在上面的代碼中,我們使用ctx.request.body獲取用戶輸入的用戶名和密碼,然後判斷輸入的用戶名和密碼是否完全匹配。當然,在真實的web項目中,通常會判斷輸入的信息與數據庫user表中的信息一致。此外,爲確保系統的安全,用戶的密碼將被加密或散列。如果輸入的用戶信息完全匹配,我們將當前登錄的用戶信息設置到該ctx.session.user屬性並重定向到首頁。並且如果用戶信息不匹配,頁面上會顯示相應的錯誤信息。

我們看一下登錄成功後服務器返回的HTTP響應報文:

 

從上圖可以看出,登錄成功後,服務器返回的HTTP響應報文中會包含Set-Cookie響應頭。之後我們打開Chrome開發者工具的Application Tab頁面,可以看到已經設置好的Cookie信息:

 

對於大部分的Web應用,一般都會提供一個用戶信息頁面,讓用戶可以查看當前已經登錄成功的用戶信息。這裏我們也註冊了一個/getUserInfo路由,用於顯示已登錄的用戶信息:

// router.js
路由器。get ( "/getUserInfo" , async (     ctx ) => {
 if ( ctx.session.user ) { const { userName, userId } = ctx.session.user ; ctx.body = ` < div         > UserName           : ${userName} , UserId: ${userId}         </div>       ` ;   } else {     ctx.body = { code : 0 , message :
   






“您還沒有登錄。” };
}
});

用戶登錄成功後,訪問web應用中的其他路由時,會發起相應的HTTP請求,請求頭中會自動攜帶當前用戶的Cookie信息,如下圖:

 

除了上述功能,我們還需要註冊一個路由來處理用戶註銷操作:

// router.js
路由器。get ( "/logout" , async (   ctx ) => {
 ctx.session = null ; ctx.body = ` < h1   >成功註銷</h1>   <a href="./login">登錄</a>   ` ; });

同樣我們看一下注銷成功後服務器返回的HTTP響應報文:

 

已經描述了包含在 Web 應用程序中的路由。爲了應用能夠正常運行,我們還需要創建一個Koa應用,並配置koa-session、koa-bodyparser等中間件。具體代碼如下:

// app.js
const  Koa = require ( "koa" );
const app = new  Koa ();
const session = require ( "koa-session" );
const bodyParser = require ( "koa-bodyparser" );

常量端口 = 3000 ;
const router = require ( "./router.js" );

const  CONFIG = {
 key : "sid" ,
 maxAge : 86400000 ,
 httpOnly: true ,
 signed : true ,
 rolling : false ,
 renew : false ,
 sameSite : null ,
};
應用程序。鍵= [ “bytefer” ];
應用程序。use ( async  function ( ctx, next     ) { try
{ await
   next ( );
} catch (err) {
   ctx.status = err.status || 500 ; ctx.type
= "html" ;
   CTX。body = "<p>系統錯誤</p>" ;
   CTX。應用程序。發出(“錯誤”,錯誤,ctx);
}
});
應用程序。使用(會話(配置,應用程序));
應用程序。使用( bodyParser ());
應用程序。使用(路由器。路由())。使用(路由器。allowedMethods());

應用程序。on ( "error" , ( err, ctx ) => {
 控制檯. 日誌(錯誤);
});

應用程序。listen (port, function ( ) {
 console . log ( `服務器運行在 http://localhost: ${port} ` );
});

Cookie-Session的認證過程已經介紹過了,最後總結一下這種認證方式存在的一些問題。

餅乾的缺陷

  • 每次HTTP請求都會添加Cookies,無形中增加了流量。
  • 安全性差,攻擊者可以利用本地 cookie 進行欺騙和 CSRF 攻擊。
  • Cookie 大小限制在 4KB 左右,不足以滿足複雜的存儲要求。

會話缺陷

  • session保存在服務器端,如果短時間內有大量用戶,會影響服務器的性能。
  • 可擴展性不好。當有多臺服務器時,如何共享Session就會成爲一個問題。也就是說當用戶第一次訪問服務器A,第二次請求轉發給服務器B時,服務器B無從知曉其狀態。

那麼如何解決以上問題呢?解決方案之一是使用基於令牌的身份驗證。在下一篇文章中,我將介紹JWT認證方式。有興趣記得關注我哦。

如果需要更加全面的學好前端,也可以來參與我們的三十天學習計劃,全程不涉及任何費用!這是一套免費的三十天挑戰計劃的課程體系,包含了html+css+雲端部署的課程體系,可以通過釘釘羣裏學習,有問題在羣裏可以提問,同時每節課還安排有作業,配套有階段項目練習和綜合項目實戰,目的是幫助大家夯實前端基礎,輕鬆入門到前端行業

 

爲幫助到一部分同學不走彎路,真正達到一線互聯網大廠前端項目研發要求,首次實力寵粉,打造了《30天挑戰學習計劃》,內容如下:

HTML/HTML5,CSS/CSS3,JavaScript,真實企業項目開發,雲服務器部署上線,從入門到精通

  • PC端項目開發(1個)
  • 移動WebApp開發(2個)
  • 多端響應式開發(1個)

共4大完整的項目開發 !一行一行代碼帶領實踐開發,實際企業開發怎麼做我們就是怎麼做。從學習一開始就進入工作狀態,省得浪費時間。

從學習一開始就同步使用 Git 進行項目代碼的版本的管理,Markdown 記錄學習筆記,包括真實大廠項目的開發標準和設計規範,命名規範,項目代碼規範,SEO優化規範

從藍湖UI設計稿 到 PC端,移動端,多端響應式開發項目開發

  • 真機調試,雲服務部署上線;
  • Linux環境下 的 Nginx 部署,Nginx 性能優化;
  • Gzip 壓縮,HTTPS 加密協議,域名服務器備案,解析;
  • 企業項目域名跳轉的終極解決方案,多網站、多系統部署;
  • 使用 使用 Git 在線項目部署;

這些內容在《30天挑戰學習計劃》中每一個細節都有講到,包含視頻+圖文教程+項目資料素材等。只爲實力寵粉,真正一次掌握企業項目開發必備技能,不走彎路 !

過程中【不涉及】任何費用和利益,非誠勿擾 。

如果你沒有添加助理老師微信,可以添加下方微信,說明要參加30天挑戰學習計劃,來自公衆號!老師會邀請你進入學習,並給你發放相關資料。

30 天挑戰學習計劃 Web 前端從入門到實戰 | arry老師的博客-艾編程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章