Node.js+Express 開發之Cookie、Session 使用詳解
為什麼有cookie 和 session ?
因為HTTP協議是沒有狀態的,當使用者再次訪問網站時,沒法判斷之前是否登陸過,於是就有了cookies和session,用來儲存使用者的一些資訊。
cookie 和 session 區別?
cookie 是存放在客戶端瀏覽器的,每個域名下通常限制為50個cookie,每個cookie 的值大小限制為4K。session 是存放在伺服器端的,可以儲存無限大的資料,但大量的session,會佔用較多的伺服器記憶體。
cookie 只能存放字串型別資料,session可以存放任意型別資料。
cookie 是儲存在瀏覽器客戶端的,所以也很容易被提取,安全方面存在隱患。session 儲存在伺服器端相對安全。
cookie的工作原理
當使用者登入網站成功,伺服器會在返回響應資料的同時,將使用者的cookie資訊也下發到客戶端,之後客戶端每次發起請求會攜帶著這個cookie,從而免去網站登入的步驟。
session的工作原理
使用者的session資料儲存在伺服器記憶體中,伺服器只下發一個session標識(session_id),它是一個唯一的隨機字串,被儲存到cookie中,下次瀏覽器的請求攜帶著包含session_id的cookie,然後伺服器在記憶體中查詢該session_id 是否有對應的資料,如果有則是已登入使用者。
看起來,session 技術相當於Cookie技術的升級,session是基於cookie的,但是cookie只是起到了 session_id 載體的作用,而url的查詢引數,http請求頭裡的欄位都可以起到session_id 載體的作用,所以沒有cookie也可以實現session。另外,使用者的session資料不僅可以存放在伺服器記憶體中,也可以存放到檔案或資料庫中,要持久化session 同時也要持久化cookie的session_id。
nodejs+express 開發中 cookie 的使用
node.js 的web框架 express 在4.x版本後,許多模組不再包含在其中,而是需要單獨下載安裝。
cookie 常用模組是 cookie-parser,安裝命令如下:
npm install cookie-parser
基本用法
程式碼示例:
let express = require("express"); let cookieParser = require("cookie-parser"); // 引用cookie-parser let app = express(); app.use(cookieParser()); // 使用cookie中介軟體cookie-parser // 首頁,讀取cookie app.get("/", function (req, res) { console.log("name: " + req.cookies.name, "profile: " + JSON.stringify(req.cookies.profile)); res.send("name: " + req.cookies.name + "<br/>" + "profile: " + JSON.stringify(req.cookies.profile)); }); // 登入,註冊cookie app.get("/login", function (req, res) { // 定義cookie引數物件 let cookieOptions = { httpOnly: true, maxAge: 10 * 60 * 1000, // 10分鐘後cookie失效 } // 建立cookie,值為字串 res.cookie("name", "xiaoyu", cookieOptions); // 建立cookie,值可以寫成json物件形式 {....} 、[...] res.cookie('profile', { age: '25', height: '160cm', weight: '50kg' }, cookieOptions); res.send("已註冊cookie"); }); // 退出,清除cookie app.get("/exit", function (req, res) { res.clearCookie("name"); res.clearCookie("profile"); res.send("已清除cookie"); }); app.listen(3000);
使用簽名cookie
使用簽名 cookie,起防篡改功能。
程式碼示例:
let express = require("express"); let cookieParser = require("cookie-parser"); // 引用cookie-parser let app = express(); app.use(cookieParser("1234567abcdefg")); // 使用cookie-parser,傳入簽名防篡改,可自定義一個複雜的字串 // 首頁,讀取cookie app.get("/", function (req, res) { console.log("name: " + req.signedCookies.name, "profile: " + JSON.stringify(req.signedCookies.profile)); res.send("name: " + req.signedCookies.name + "<br/>" + "profile: " + JSON.stringify(req.signedCookies.profile)); }); // 登入,註冊cookie app.get("/login", function (req, res) { // 定義cookie引數物件 let cookieOptions = { httpOnly: true, maxAge: 10 * 60 * 1000, // 10分鐘後cookie失效 signed: true // 使用簽名 } // 建立cookie,值為字串 res.cookie("name", "xiaoyu", cookieOptions); // 建立cookie,值可以寫成json物件形式 {....} 、[...] res.cookie('profile', { age: '25', height: '160cm', weight: '50kg' }, cookieOptions); res.send("已註冊cookie"); }); // 退出,清除cookie app.get("/exit", function (req, res) { res.clearCookie("name"); res.clearCookie("profile"); res.send("已清除cookie"); }); app.listen(3000);
cookie 引數選項說明:
domain:表示cookie在什麼域名下有效,預設為當前網站域名。如果跨域訪問,A站域名為 A.test.com,B站域名為 B.test.com,那麼在域A生產一個令域A和域B都能訪問的cookie就要將該cookie的domain設定為: ".test.com"
expires:cookie過期時間,型別為Date。例如:expires: new Date(Date.now() + 10*60*1000) 表示10分鐘後cookie過期。如果沒有設定或者設定為0,那麼該cookie 在關閉瀏覽器後失效。expires早在http/1.0中已經定義,max-age在http/1.1中定義, 現在基本都是http/1.1,expires已經被max-age屬性所取代,建議優先使用maxAge
maxAge:和expires類似,設定cookie過期的時間,指明從現在開始,多少毫秒以後cookie到期。maxAge:10*60*1000 表示10分鐘後Cookie過期。 完全不寫 maxAge 項,只要關閉瀏覽器cookie就失效。maxAge:0 表示從客戶端刪除此cookie。
httpOnly:禁止JS指令碼document.cookie 讀取cookie內容,防止XSS攻擊產生. 預設為false。建議設定為true
path:cookie在什麼路徑下有效,預設為'/'
secure:當secure值為true時,cookie在HTTP中是無效,只在HTTPS中才有效。預設為false
signed:使用簽名,起到防篡改功能。預設為false。 此項並不是加密,cookie值仍然被明文顯示出來,對於cookie的加密可自己使用md5、sha1、hmac、aes等方法,或使用中介軟體cookie-encrypter
對 cookie 加密
這裡使用第三方模組 cookie-encrypter 對cookie 進行加密。該模組預設採用的是AES256 對稱加密演算法
安裝cookie-encrypter
npm install cookie-encrypter
程式碼示例
let express = require("express"); let cookieParser = require("cookie-parser"); let cookieEncrypter = require("cookie-encrypter"); // 引用cookie-encrypter 模組 let app = express(); const secretKey = 'foobarbaz1234567foobarbaz1234567'; // 預設cookie-encrypter模組使用的是 AES256 加密演算法,須輸入32個字元 app.use(cookieParser(secretKey)); app.use(cookieEncrypter(secretKey)); // 傳入金鑰,加密cookie,主要是這句 app.get("/", function (req, res) { console.log("name: " + req.signedCookies.name, "profile: " + JSON.stringify(req.signedCookies.profile)); res.send("name: " + req.signedCookies.name + "<br/>" + "profile: " + JSON.stringify(req.signedCookies.profile)); }); app.get("/login", function (req, res) { let cookieOptions = { httpOnly: true, signed: true, maxAge: 10 * 60 * 1000, // plain: true // 該選項是cookie-encrypter模組的選項。等於true時,表示不再使用cookie-encrypter進行加密。 }; res.cookie('name', 'xiaoyu', cookieOptions); res.cookie('profile', { age: '25', height: '160cm', weight: '50kg' }, cookieOptions); res.send("已註冊cookie"); }); app.get("/exit", function (req, res) { res.clearCookie('name'); res.clearCookie('profile'); res.send("已清除cookie"); }); app.listen(3000);
nodejs+express 開發中 session 的使用
處理session常用的中介軟體之一是 express-session
安裝 express-session 模組,命令如下:
npm install express-session
程式碼示例
let express = require("express"); let session = require("express-session"); let app = express(); app.use(session({ secret: "nodejs world", resave: false, saveUninitialized: false, name: "session_id", rolling: true, cookie: { path: '/', httpOnly: true, secure: false, maxAge: 30 * 60 * 1000 // 設定session_id的cookie有效時間,也是後臺session的有效時長。(預設為值為null,當關閉瀏覽器時,session_id cookie失效)。 } })); app.get("/", function (req, res) { if (req.session.login) { res.send("歡迎您" + req.session.userName + ", " + req.sessionID); } else { res.send("你沒有登入!"); } }); app.get("/login", function (req, res) { req.session.login = true; req.session.userName = "xiaoyu"; res.send("您已經成功登入"); }); app.get("/exit", function (req, res) { req.session.destroy(); res.send("您已經退出"); }); app.listen(3000);
session 配置選項說明
secret: 對session_id cookie的簽名金鑰。
resave: 強制儲存 session 即使它並沒有變化。預設為true,建議設定成false
saveUninitialized: 強制將未初始化的session儲存。預設為 true。 設定為true 不管用不用到session都會初始化。設定為false 用到session時才會去初始化。
name: 這裡設定session_id 的cookie的名字。預設名為 'connect.sid'
rolling: 在每次請求時強行設定cookie,這將重置session-id 的 cookie過期時間。預設:false
cookie: session_id 的cookie 選項。預設值是 { path: '/', httpOnly: true, secure: false, maxAge: null }
將session 存放在 mongoDB 資料庫中
session 預設存放在記憶體中,也可以存放到 redis,mongodb 等資料庫中。express 生態中都有相應模組支援。
將session儲存到mongodb 資料庫,可以安裝connect-mongo模組支援
npm install connect-mongo
程式碼示例
let express = require("express"); let session = require("express-session"); let MongoStore = require('connect-mongo')(session); // 引用 connect-mongo let app = express(); app.use(session({ secret: "nodejs world", resave: false, saveUninitialized: false, name: "session_id", rolling: true, cookie: { path: '/', httpOnly: true, secure: false, maxAge: 30 * 60 * 1000 // session_id cookie 和 session的有效時長 }, store: new MongoStore({ url: 'mongodb://localhost:27017/mydb', // 指定mongoDB 主機地址、埠、資料庫 ttl: 30*60 // 設定session過期時間,時間到自動移除。單位秒。一般設定為30分鐘即可。未設定cookie:maxAge時有效。 }) })); app.get("/", function (req, res) { if (req.session.login) { res.send("歡迎您" + req.session.userName + ", " + req.sessionID); } else { res.send("你沒有登入!"); } }); app.get("/login", function (req, res) { req.session.login = true; req.session.userName = "xiaoyu"; res.send("您已經成功登入"); }); app.get("/exit", function (req, res) { req.session.destroy(); res.send("您已經退出"); }); app.listen(3000);
將session 存放在 redis 資料庫中
將session儲存到redis 資料庫,可以安裝redis-mongo模組支援。事先需安裝好redis的nodejs客戶端
npm install redis npm install connect-redis
程式碼示例
let express = require("express"); let session = require("express-session"); let redis = require("redis"); // 引用redis客戶端 let RedisStore = require('connect-redis')(session); // 引用connect-redis let app = express(); let redisClient = redis.createClient({ // 設定redis 主機地址、埠、資料庫、密碼 host: "localhost", port: "6379", //password: "123456", db: 1 }); app.use(session({ secret: "nodejs world", resave: false, saveUninitialized: false, name: "session_id", rolling: true, cookie: { path: '/', httpOnly: true, secure: false, maxAge: 30 * 60 * 1000 // session_id cookie 和 session的有效時長 }, store: new RedisStore({ client: redisClient, // 指定redis客戶端 ttl: 30 * 60, // 設定session過期時間,時間到自動移除。單位秒。一般設定為30分鐘即可。未設定cookie:maxAge時有效。 logErrors: true, // 是否列印redis出錯資訊,預設false prefix: "sess:" // key字首,預設為 "sess:" }) })); app.get("/", function (req, res) { if (req.session.login) { res.send("歡迎您" + req.session.userName + ", " + req.sessionID); } else { res.send("你沒有登入!"); } }); app.get("/login", function (req, res) { req.session.login = true; req.session.userName = "xiaoyu"; res.send("您已經成功登入"); }); app.get("/exit", function (req, res) { req.session.destroy(); res.send("您已經退出"); }); app.listen(3000);
相關文章
- Cookie & Session詳解CookieSession
- Cookie與Session詳解CookieSession
- Cookie,Session Filter,Listener詳解CookieSessionFilter
- http協議/cookie詳解/session詳解HTTP協議CookieSession
- cookie和session的詳解與區別CookieSession
- cookie與session的區別(圖文詳解)CookieSession
- cookie與session的使用CookieSession
- nodeJS之Cookie和Session(一)NodeJSCookieSession
- Django框架之Cookie和SessionDjango框架CookieSession
- Cookie&Session概念解讀CookieSession
- cookie sessionCookieSession
- cookie & sessionCookieSession
- Laravel 探索之 Session 與 Cookie 結構LaravelSessionCookie
- Django基礎六之cookie和sessionDjangoCookieSession
- cookie 和 sessionCookieSession
- session和cookieSessionCookie
- cookie&sessionCookieSession
- Session與CookieSessionCookie
- Cookie和SessionCookieSession
- 你真的瞭解 Cookie 和 Session 嗎CookieSession
- 你真的瞭解 Cookie 和 Session 嗎?CookieSession
- 你真的瞭解 Session 和 Cookie 嗎?SessionCookie
- v$Session詳解Session
- cookie與session的自己思考與解釋CookieSession
- cookie、session總結CookieSession
- Cookie&Session&JSPCookieSessionJS
- 理解 cookie、session、tokenCookieSession
- Django Cookie與SessionDjangoCookieSession
- cookie、session、web storageCookieSessionWeb
- 【Javaweb】Cookie和SessionJavaWebCookieSession
- iOS開發之 Autolayout 詳解iOS
- java基礎學習:JavaWeb之Cookie和SessionJavaWebCookieSession
- Web 開發必須掌握的三個技術:Token、Cookie、SessionWebCookieSession
- HttpServletRequest使用者請求與cookie詳解HTTPServletCookie
- Livy Session 詳解(上)Session
- session和cookie關係SessionCookie
- Session和Cookie機制SessionCookie
- Cookie與Session 關係CookieSession