流程大體以下:html
session會話保存到redis集羣中,實現服務器共享session。前端
D:\redis
requirepass ****
,以下圖:redis-server.exe
使用本地配置啓動redisnode
cd D:\redis redis-server.exe redis.windows.conf
運行redis-cli.exe
以鏈接到您的redis實例react
cd D:\redis redis-cli.exe
PS:若是報了(error) NOAUTH Authentication required.是由於設置了認證密碼,須要輸入密碼(就是上面設置的密碼)進行認證登入jquery
Redis React是一個簡單易用的用戶界面,用於瀏覽Redis服務器中的數據,該數據由React桌面模板構建,可在Windows,OSX,Linux等多種平臺上使用,也能夠部署爲自託管控制檯或ASP.NET Web應用程序。git
Redis React充分利用了基於Web的UI的導航和深層連接優點,React框架的生產力和響應能力 以及本機桌面應用程序提供的豐富的本機體驗和OS集成。github
下載鏈接:https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact-winforms.exe,下載完直接執行便可ajax
在本地啓動redis就能夠輕鬆的模擬redis集羣,全部其餘服務器直接鏈接redis就能夠了redis
本文後臺使用nodeJs實現,生成session和操做redis依賴express-session
、connect-redis
、redis
三個庫。sql
express-session
:中間件,用於在後端生成sessionID和cookie,會在request流對象中生成一個Session對象,用於操做session。connect-redis
:這是一個關於session的持久化插件, 配合express-session
使用。此模塊基於redis,將session相關信息持久化(意思就是將session存入redis)。redis
:用於鏈接和操做redis數據庫。
使用方式大體以下:
const express = require("express") const session = require('express-session') const RedisStrore = require('connect-redis')(session) const redis = require('redis') const config={ "cookie" : { "path": "/", "maxAge" : 1800000, "httpOnly": true }, "sessionStore" : { "host": "127.0.0.1", // redis主機 "port": "6379", // redis默認端口號 "pass": "****", "auth_pass": "****", // 設置了密碼時須要該字段 } } const app = express() const client = redis.createClient(6379, '127.0.0.1', config.sessionStore) // 鏈接redis,建立實例 app.use(session({ name : "sessionId", // sessionID的屬性名 secret : 'Asecret123-', // 生成sessionID的密鑰 resave : false, rolling: false, //在每次請求時強行設置 cookie,這將重置 cookie 過時時間(默認:false) saveUninitialized : false, // 強制將未初始化的 session 存儲。當新建了一個 session 且未設定屬性或值時,它就處於未初始化狀態。在設定一個 cookie 前,這對於登錄驗證,減輕服務端存儲壓力,權限控制是有幫助的。(默 認:true)。建議手動添加。 cookie: config.cookie, store: new RedisStrore({ client }) }));
使用後request流對象會新增sessionID字段和session對象
前端部分:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script> </head> <body> <div id="app">home</div> <button onclick="logout()">退出</button> </body> </html> <script> $.ajax({ url: "http://127.0.0.1:1001/getData", method: 'GET', dataType: 'json', xhrFields: { withCredentials: true //容許攜帶Cookie }, success: function(res) { console.log(res) if (res.code === 401) { window.location.href = "http://127.0.0.1:2000/?redirect_url=" + encodeURIComponent(window.location.href) } else if (res.code === 200) { $("#app").text(res.data.msg) } } }) function logout() { $.ajax({ url: "http://127.0.0.1:1001/logout", method: 'GET', dataType: 'json', xhrFields: { withCredentials: true //容許攜帶Cookie }, success: function(res) { if (res.code === 200) { // 不能再這裏操做document.cookie來刪除sessionId,由於設置了httpOnly window.location.reload() } } }) } </script>
後端部分:
// 攔截器 app.all('*', function(req, res, next) { if (req.cookies.sessionId) { var sessionId = req.cookies.sessionId.split('.')[0].replace("s:", "sess:") console.log('sessionId', sessionId) client.get(sessionId, function(err, reply) { console.log('reply', reply) if (reply) { next(); } }) } else { console.log("=============重定向到SSO=============") res.json({ code: 401 }) } }) app.get('/getData', (req, res) => { res.json({ code: 200, data: { msg: 'hello, welcome you!' } }) }) app.get('/logout', (req, res) => { req.session.destroy(err => { if (err) throw new ErrorEvent("註銷失敗") res.clearCookie("sessionId").json({ code: 200 }) }) })
初始進入頁面發送http://127.0.0.1:1001/getData請求,若是沒有攜帶cookie,後臺攔截器就會攔截,返回401,前臺判斷是401就重定向到SSO
前端部分:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>login</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script> </head> <body> <div> <label>帳戶:</label> <input type="text" class="account" name="account" value=""> </div> <div> <label>密碼:</label> <input type="text" class="password" name="password" value=""> </div> <div> <input type="button" onclick="submit()" value="登陸"> <input type="reset" value="重置"> </div> </body> </html> <script> // 獲取url參數 function getQueryVariable(variable) { var query = window.location.search.substring(1); var vars = query.split("&"); for (var i=0;i<vars.length;i++) { var pair = vars[i].split("="); if(pair[0] == variable){return pair[1];} } return(false); } function submit() { var account = $(".account").val().trim() var password = $(".password").val().trim() if (!account || !password) { alert("帳戶密碼不能爲空") } $.ajax({ url: 'http://127.0.0.1:2001/login', method: 'POST', data: { account, password }, dataType: 'json', contentType: 'application/x-www-form-urlencoded', xhrFields: { withCredentials: true //容許攜帶Cookie }, success: function(res) { if (res.code === 200) { setTimeout(() => { window.location.href = decodeURIComponent(getQueryVariable("redirect_url")) }, 1000); } } }) } </script>
後臺部分:
app.post('/login', (req, res) => { var account = req.body.account var pwd = req.body.password if (!account || !pwd) { console.log("帳戶密碼不能爲空") return } nosql.one().make(builder => { builder.where('account', '=', account); builder.where('password', '=', pwd); builder.callback((err, userInfo) => { if (userInfo) { req.session.regenerate(err => { if (err) { console.log('生成sessionID失敗: ' + err) } else { console.log(req) req.session.userInfo = userInfo req.session.save() // res.cookie("sessionId", req.sessionID, req.session.cookie) res.json({ code: 200 }) } }) } else { console.log("該帳戶不存在") } }) }) })
這裏數據庫使用的是nosql文檔數據庫,依賴nosql
模塊。登陸成功後regenerate方法會生成session和cookie,而後將session保存到redis中
PS:存在cookie中的sessionID和存在redis中的sessionID不同,這是由於express-session底層實現的緣由,有興趣的同窗能夠深刻一下
項目地址:https://github.com/Revelation...
https://segmentfault.com/a/11...
https://github.com/ServiceStackApps/RedisReact#download