cookie?session?jwt 寫在前面
PS:已經有很多文章寫過這些東西了,我寫的目的是為了自己的學習。所學只是為了更好地了解用戶登錄鑒權問題。
我們都知道HTTP是一個無狀態的協議
什么是無狀態?
用http協議進行兩臺計算機交互時,無論是服務器還是瀏覽器端,http協議只負責規定傳輸格式,你怎么傳輸,我怎么接受怎么返回。它并沒有記錄你上次訪問的內容,你上次傳遞的參數是什么,它不管的。
回到我們要解決的問題,就是用戶登錄到了一個網站(index.html),然后點擊主頁上的某一個超鏈接跳轉到其他頁面(another.html),這個時候你在another.html頁面就沒有了登陸狀態。這樣意味著我們每次跳轉一個頁面都要進行一次登陸操作,這是極其不合理的。
為了保證登錄信息以及狀態信息能夠傳遞下去,就引入了其他機制
session和cookie Cookie(1)cookie是實際存在的,存在于客戶端,用戶可見可修改,不安全。
(2)cookie在一個域名下是全局的,只要設置path為/,即可從該域名下的任意頁面讀取cookie中的信息。
(3)為了安全,HttpOnly設置為true,這樣可以一定程度上的預防XSS(跨站腳本攻擊)
(4)瀏覽器禁用cookie之后,這種情況下會使用url重寫的技術來進行會話跟蹤,即在url后面加上sid=xxx參數。
大多數應用都是基于cookie來實現session跟蹤的。
Sessionsession是一種機制,并不實際存在,它由服務器負責管理。關閉瀏覽器之后,session就會丟失。
具體的過程如下:
(1)客戶端第一次發送請求到服務器,服務器生成一個唯一的sessionId,一個sessionId對應一個用戶,該sessionId可以存放在Redis或者mongodb中,具體存放在哪里看個人選擇
(2)后端將該sessionId放到響應頭的Set-Cookie字段,返給前端。
(3)前端記下該sessionId并放到cookie字段,之后每次客戶端請求服務器時都會在請求頭帶上cookie字段,服務端根據sessionId來獲取具體信息(比如TTL,過期時間,用戶id)
Koa2中使用session首先當然是引入包了啊,這里選擇了koa-session2`。koa-session2`已經幫你做好了所有,使用起來相當簡單,方便快速開發。
const Koa = require("koa") const app = new Koa() const session = require("koa-session2") app.use(session({ stort: new RedisStore(), //存放session的地方,我這里選擇放到redis里 key: "SESSION_ID" }))
new RedisStore()又是什么呢?其實查看koa-session2的git倉https://github.com/Secbone/koa-session2就能知道
以下來自官方git倉:
const Redis = require("ioredis"); const { Store } = require("koa-session2"); class RedisStore extends Store { constructor() { super(); this.redis = new Redis(); // 連接redis } async get(sid, ctx) { let data = await this.redis.get(`SESSION:${sid}`); return JSON.parse(data); } async set(session, { sid = this.getID(24), maxAge = 1000000 } = {}, ctx) { try { // Use redis set EX to automatically drop expired sessions // 設置redis的Ex 以自動丟棄過期的session await this.redis.set(`SESSION:${sid}`, JSON.stringify(session), "EX", maxAge / 1000); } catch (e) {} return sid; } async destroy(sid, ctx) { // 刪除redis中的數據 return await this.redis.del(`SESSION:${sid}`); } } module.exports = RedisStore;
接下來就是判斷登陸,以及將需要的信息寫入session
let sid = ctx.cookies.get("SESSION_ID") // 獲得cookie中的sid ctx.session.myinfo = {a: 1, b: 2} //將一個數據對象放到session中 // 最后的結果就是: // redis中的鍵為SESSION:sid // 值為{myinfo: {a: 1, b: 2}}
當你退出時,清空cookie和session即可
ctx.cookies.set("SESSION_ID", "") ctx.session = nullJWT 簡答認識JWT
讓我們來看看重頭戲JWT,全稱JSONWebToken,是一種目前較為流行的驗證方式。
JWT由三部分組成,第一部分我們稱它為頭部(header),
//header { "typ": "JWT", // 類型 "alg": "HS256" // 加密算法 } // 對其base64 得到了第一個部分
第二部分我們稱其為載荷(payload, 類似于飛機上承載的物品)
// payload 存放有效信息的地方 比如userId { "id": "1234567890", "name": "John Doe", "isMan": true } // 對其base64 得到第二個部分
第三部分是簽證(signature).
// 將base64后的header和base64后的payload使用.連接組成新的字符串,然后使用header中聲明的加密方式對其進行加鹽secret組合加密,得到了第三個部分
將三部分用.連接成一個完整的字符串,得到了最終的jwt。
注意:
不應該在jwt的payload部分存放敏感信息,因為該部分是客戶端可解密的部分。
保護好secret私鑰,該私鑰非常重要。
如果可以,請使用https協議
具體的過程如下:
(1)客戶端第一次發送請求到服務端,服務器驗證用戶信息
(2)服務端生成一個token發送給客戶端
(3)客戶端保存token,之后每次請求時帶上這個token
(4)服務端驗證token,返回數據。
與session的過程是類似的,但是缺少了將jwt保存到服務端,這樣便于擴展,不會因為登錄到不同的服務器導致session無法共享。
Koa2中使用jwt第一步當然還是下包。。npm install jsonwebtoken
const jwt = require("jsonwebtoken")
服務端生成token,并返給前端
// 生成token const token = jwt.sign({role: user.role, id: user._id}, key, {expiresIn: "1 days"}) // 第一個參數為負載的信息,第二個參數為secret,第三個參數我是過期時間 // 返回前端 ctx.body = { token: token }
客戶端之后發起請求,應該帶上token字段,將其放在authorization請求頭字段或者以query的方式。
if(ctx.header.authorization && ctx.headers.authorization.split(" ")[0] === "Bearer") { token = ctx.header.authorization.split(" ")[1] } else if(ctx.query && ctx.query.token) { token = ctx.query.token }
然后服務端驗證token,進行相應的處理返回數據。
// 解密token 一般使用jwt.verify不適用jwt.decode let decoded = jwt.verify(token, key) // 得到token中包含的信息對象
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/94670.html
摘要:由于是存在客戶端上的,所以瀏覽器加入了一些限制確保不會被惡意使用,同時不會占據太多磁盤空間。簽名是對前兩部分的簽名,防止數據被篡改。的作用最開始的初衷是為了實現授權和身份認證作用的,可以實現無狀態,分布式的應用授權。 前言 無狀態的HTTP協議 很久很久之前, Web基本都是文檔的瀏覽而已。既然是瀏覽, 作為服務器, 不需要記錄在某一段時間里都瀏覽了什么文檔, 每次請求都是一個新的HT...
摘要:為用戶提供授權以允許用戶操作非公開資源,有很多種方式。具體的代碼根據不同的授權方案而有所不同。使用授權原理利用來驗證用戶,有兩種機制實現。使用來實現用戶授權主要用于簽發如果有將異步的簽名。注意這里的與之前用于簽發的應該是同一個。 在很多應用中,我們都需要向服務端提供自己的身份憑證來獲得訪問一些非公開資源的授權。比如在一個博客平臺,我們要修改自己的博客,那么服務端要求我們能夠證明 我是...
摘要:為用戶提供授權以允許用戶操作非公開資源,有很多種方式。具體的代碼根據不同的授權方案而有所不同。使用授權原理利用來驗證用戶,有兩種機制實現。使用來實現用戶授權主要用于簽發如果有將異步的簽名。 ? 在很多應用中,我們都需要向服務端提供自己的身份憑證來獲得訪問一些非公開資源的授權。比如在一個博客平臺,我們要修改自己的博客,那么服務端要求我們能夠證明 我是我 ,才會允許我們修改自己的...
摘要:客戶端發起非登錄請求時,服務端通過中的找到對應的來知道此次請求是誰發出的。數量隨著登錄用戶的增多而增多,存儲會增加很多。還記得在上家公司做全干工程師的時候,基本從頁面寫到運維,當時做登錄這塊的時候,被session、cookie、token各種概念差點整蒙圈了,上網查詢相關概念,發現很多人都是類似的疑惑,比如:showImg(https://user-gold-cdn.xitu.io/201...
閱讀 996·2023-04-26 01:47
閱讀 1680·2021-11-18 13:19
閱讀 2048·2019-08-30 15:44
閱讀 659·2019-08-30 15:44
閱讀 2301·2019-08-30 15:44
閱讀 1239·2019-08-30 14:06
閱讀 1428·2019-08-30 12:59
閱讀 1906·2019-08-29 12:49