日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

前端登陆之cookie篇

發布時間:2024/3/13 HTML 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端登陆之cookie篇 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、cookie

上一個文章介紹了實用node寫了一個服務,以及調用api去操作數據庫的一個前后端分離的demo,這次重點記錄一下前后端登陸操作的一個部分。登陸認證是一個項目中比較重要的部分,接下來我將使用cookie的模式來實現登陸認證!

cookie的組成

cookie是瀏覽器中特有的一個概念,它就像瀏覽器的專屬卡包,管理著各個網站的身份信息。

每個cookie就相當于是屬于某個網站的一個卡片,它記錄了下面的信息:

  • key:鍵,比如「身份編號」

  • value:值,比如張博的身份編號「14563D1550F2F76D69ECBF4DD54ABC95」,這有點像卡片的條形碼,當然,它可以是任何信息

  • domain:域,表達這個cookie是屬于哪個網站的,比如123.com,表示這個cookie是屬于123.com這個網站的

  • path:路徑,表達這個cookie是屬于該網站的哪個基路徑的,就好比是同一家公司不同部門會頒發不同的出入證。比如/news,表示這個cookie屬于/news這個路徑的。(后續詳細解釋)

  • secure:是否使用安全傳輸

  • expire:過期時間,表示該cookie在什么時候過期

當瀏覽器向服務器發送一個請求的時候,它會瞄一眼自己的卡包,看看哪些卡片適合附帶捎給服務器

如果一個cookie同時滿足以下條件,則這個cookie會被附帶到請求中

  • cookie沒有過期

  • cookie中的域和這次請求的域是匹配的

  • 比如cookie中的域是123.com,則可以匹配的請求域是123.com、www.123.com、234.123.com等等

  • 比如cookie中的域是www.123.com,則只能匹配www.123.com這樣的請求域

  • cookie是不在乎端口的,只要域匹配即可

  • cookie中的path和這次請求的path是匹配的

  • 比如cookie中的path是/news,則可以匹配的請求路徑可以是/news、/news/detail、/news/a/b/c等等,但不能匹配/blogs

  • 如果cookie的path是/,可以想象,能夠匹配所有的路徑

  • 驗證cookie的安全傳輸

  • 如果cookie的secure屬性是true,則請求協議必須是https,否則不會發送該cookie

  • 如果cookie的secure屬性是false,則請求協議可以是http,也可以是https

如果一個cookie滿足了上述的所有條件,則瀏覽器會把它自動加入到這次請求中

具體加入的方式是,瀏覽器會將符合條件的cookie,自動放置到請求頭中。

如果把它用于登錄場景,就是如下的流程:

登錄請求

  • 瀏覽器發送請求到服務器,附帶賬號密碼

  • 服務器驗證賬號密碼是否正確,如果不正確,響應錯誤,如果正確,在響應頭中設置cookie,附帶登錄認證信息(至于登錄認證信息是設么樣的,如何設計,要考慮哪些問題,就是另一個話題了,可以百度 jwt)

  • 客戶端收到cookie,瀏覽器自動記錄下來

  • 后續請求

  • 瀏覽器發送請求到服務器,希望添加一個管理員,并將cookie自動附帶到請求中

  • 服務器先獲取cookie,驗證cookie中的信息是否正確,如果不正確,不予以操作,如果正確,完成正常的業務流程

  • 二、處理登陸APi接口

    接下來就是處理登陸這個api接口:

    const express = require("express") const router = express.Router() const user = require("../../serveAPI/userService") const {asyncHandler} = require("../getResult") const cryptor = require("../../util/crypt")router.post("/login",asyncHandler(async (req,res,next) =>{const result = await user.login(req.body.loginId,req.body.loginPwd)if (result) {//如果result存在則登錄成功//設置cookie//給瀏覽器用cookie//cookie-parse給了一個默認加密,其中有默認密鑰可以設置const value = result.idcryptor.encrypt(value)res.cookie("token",result.id,{path:"/",domain:"localhost",maxAge:3600*24*10000,// signed:true,})//給其他應用 如手機端res.header("authorization",value)}return result;} ))

    當我們調用這個接口之后,就會從數據庫中訪問這個用戶(根據用戶名和密碼),這個密碼時使用md5進行加密,然后解密的:

    當返回這個結果的時候,我們就使用cooke方法進行給res請求結果中設置cookies,將token設為用戶的id,剩下的domain,還有path,maxAge都可以視情況而定,但是這里的id就可以在瀏覽器端使用document.cookie獲取到,然后提取出來id,我們在服務端,也可以設置讓js不能獲取cookie,防止跨站腳本攻擊,但是還是不安全,因為這個數據是明文的,可以在瀏覽器中的cookie中看到數據,而cookie-parse里面提供一個自動加密的屬性,就是signed為true,就會給這個cookie里的token值自動加密,之后取到也可以自動解密,但是有個很嚴重的問題,這里cookie是瀏覽器特有的一個屬性,在其他端雖然可以使用但是沒有像瀏覽器這樣專門設置這個cookie模塊,來處理請求,所以我們在這個請求頭中,留一手,給請求頭中再設置一個authorization的值為用戶id,這樣不管是pad端,手機端都可以處理這個請求內容,所以當設置這個authorization這個鍵之后,cookie-parse只能去處理這個cookie中的token而不能處理authorization,所以加密這個事情還得我們來做,這里使用node里面提供的這個crypto模塊,來進行加密:

    const secret = Buffer.from("mm7h3ck87ugk9l4a"); const crypto = require("crypto"); const iv = Buffer.from("jxkvxz97409u3m8c");//加密一個字符串 exports.encrypt = function (str) {const cry = crypto.createCipheriv("aes-128-cbc", secret, iv);let result = cry.update(str, "utf-8", "hex");result += cry.final("hex");return result; };//解密一個字符串 exports.decrypt = function (str) {const decry = crypto.createDecipheriv("aes-128-cbc", secret, iv);let result = decry.update(str, "hex", "utf-8");result += decry.final("utf-8");return result; };

    上面是一個js文件導出兩個函數,一個用于加密,一個用語解密;

    使用對稱加密算法:aes算法 128位密鑰(16個字節的字符串),其中mm7h3ck87ugk9l4a是用隨機數轉字符串拼接獲取Math.random(),toString(36).slice(-8)+Math.random(),toString(36).slice(-8)

    Buffer是node里面的一個類,JS里的String對象,存儲的是字符串,而且是Unicode編碼的。

    我們使用node內置庫crypto,crypto.getCiphers()可以看到crypto所有的加密函數,而我們使用第一個aes-128-cbc,接下來是準備一個iv,隨機向量 ,一般來說密鑰固定,向量是不固定的,這里我為了簡便實用固定的。而這個密鑰是存儲在服務端的,所以很難進行解密,這樣就會讓數據有安全保障。第一層保障是這個密鑰,如果這個密鑰泄漏,下一個保障就是iv向量,這里寫的固定的,當然也可以寫那種不固定的,使用到js中的閉包;

    module.exports = function(){//準備一個ivconst iv = Buffer.from(Math.random(),toString(36).slice(-8)+Math.random(),toString(36).slice(-8));return {encrypt(str){const cry = crypto.createCipheriv("aes-128-cbc", secret, iv);let result = cry.update(str, "utf-8", "hex");result += cry.final("hex");return result;},decrypt(str){const decry = crypto.createDecipheriv("aes-128-cbc", secret, iv);let result = decry.update(str, "hex", "utf-8");result += decry.final("utf-8");return result;},} }

    這里我們直接導出一個函數,這個函數執行后就會給予一個對象,對象有兩個方法,第一個是加密,第二個是解密,而這兩個函數都使用到函數里定義的變量iv,當我們調用一次這個函數,就會生成一個iv,所以這個iv是不固定的,也是無法獲取的,這樣就完善了token加密的一個步驟,讓數據更加的安全!

    三、使用中間件獲取cookie

    我們使用cookie-parser插件寫入中間件,之后再每一次的請求中都會在req對象中注入cookies屬性,用于獲取傳遞過來的cookie,也會在res對象中注入獲取cookie的方法,所以操作起來就更加方便。

    我們引入自己寫的cookieMiddleware中間件

    /*** 用于解析token*/ const { getErr } = require("./getResult"); const cryptor = require("../util/crypt")// 用于解析token module.exports = (req, res, next) => {let token = req.cookies.token;// 獲取cokkie // let token = req.signedCookies.token;if(!token){//其他的端獲取tokentoken = req.headers.authorization}if(!token){handleNonToken(req,res,next)return;}const userId = cryptor.decrypt(token)console.log(userId,"認證通過啦~~~");next() };//處理沒有認證的情況 function handleNonToken(req, res, next) {res.status(403).send(getErr("不好意思,您沒有token令牌無法登陸哦~", 403)); }

    以上可以看出,當我們調用接口的時候,就會進行token認證,首先從req中獲取cookie如果沒有的話,就會在authorization中獲取,如果都沒有那么就報錯,如果有一個有,就進行解密,然后執行下一個中間件,至此,使用cookie方式登陸的模式完成!

    總結

    以上是生活随笔為你收集整理的前端登陆之cookie篇的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。