搜尋
首頁web前端js教程Node實戰:運用Cookie&Session進行登入驗證

Node實戰:運用Cookie&Session進行登入驗證

原文網址:https://ailjx.blog.csdn.net/article/details/127909213

作者:海底烤肉店ai

在前面的幾節中我們已經創建並優化好了簡易使用者管理系統的專案結構,也對Cookie-Session登入驗證 的工作原理做了講解,接下來我們將繼續補充這個系統的功能,這一節我們將實戰運用Cookie-Session來實現這個系統的登入驗證功能。 【相關教學推薦:nodejs影片教學

什麼?你還不了解sessioncookie!快去看看上篇文章:詳解Cookie-Session登入驗證的工作原理

#1️⃣ 定義頁面路由

#在vies目錄下新建login.ejs

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1 id="登录页面">登录页面</h1>
    <div>用户名:<input type="text" id="username"></div>
    <div>密码:<input type="password" id="password"></div>
    <div><button id="login">登录</button></div>
    <script>
        const uname = document.getElementById("username");
        const pwd = document.getElementById("password");
        const login = document.getElementById("login");
        login.onclick = () => {
            fetch(&#39;/api/login&#39;, {
                method: &#39;POST&#39;,
                body: JSON.stringify({
                    username: uname.value,
                    password: pwd.value
                }),
                headers: {
                    "Content-Type": "application/json"
                }
            }).then(res => res.json()).then(res => {
                // console.log(res);
                if (res.ok) {
                    location.href = "/"
                } else {
                    alert("用户名密码不匹配!")
                }
            })
        }
    </script>
</body>

</html>

注意:頁面中請求的介面是POST /api/login請求

routes目錄下新建login.js,該檔案定義login頁面的頁面路由:

var express = require("express");
var router = express.Router();

/* GET login page. */
router.get("/", function (req, res, next) {
    res.render("login");
});

module.exports = router;

app.js中掛載頁面路由:

// 引入
var loginRouter = require("./routes/login");
// 挂载
app.use("/login", loginRouter);

啟動項目,訪問http://localhost:3000/login正常顯示:

Node實戰:運用Cookie&Session進行登入驗證

2️⃣ 定義API介面

services/UserService.js中定義介面的模型(M層):

const UserService = {
	// .......
    // 登录查询
    login: (username, password) => {
    	// 向数据库查询该用户
        return UserModel.findOne({ username, password });
    },
};

controllers/UserController.js中定義介面的控制層(C層) :

const UserController = {
 	// ......
 	// 登录验证
    login: async (req, res, next) => {
        try {
            const { username, password } = req.body;
            const data = await UserService.login(username, password);
            // console.log(data);
            if (data) {
                res.send({ ok: 1, msg: "登录成功!", data });
            } else {
                res.send({ ok: 0, msg: "用户不存在,登录失败!" });
            }
        } catch (error) {
            console.log(error);
        }
    },
};

routes/users.js中定義Api路由:

// 登录校验
router.post("/login", UserController.login);

至此登入頁面就建置好了:

Node實戰:運用Cookie&Session進行登入驗證

3️⃣ 設定session

在上一節Cookie-Session登入驗證工作原理的介紹中我們知道:

Node實戰:運用Cookie&Session進行登入驗證

圖一

這個過程顯然是比較複雜的,在express中有一個 express-session模組可以大幅降低我們的工作量,讓我們站在巨人的肩膀上開發!

下載express-session

npm i express-session

app.js中進行設定:

// 引入express-session
var session = require("express-session");

// 配置session:需要放在在路由配置的前面
app.use(
    session({
        name: "AilixUserSystem", // cookie名字
        secret: "iahsiuhaishia666sasas", // 密钥:服务器生成的session的签名
        cookie: {
            maxAge: 1000 * 60 * 60, // 过期时间:一个小时过期
            secure: false, // 为true时表示只有https协议才能访问cookie
        },
        resave: true, // 重新设置session后会重新计算过期时间
        rolling: true, // 为true时表示:在超时前刷新时cookie会重新计时;为false表示:在超时前无论刷新多少次,都是按照第一次刷新开始计时
        saveUninitialized: true, // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活的信用卡
    })
);

配置好後,就會發現瀏覽器中有一個名為AilixUserSystemcookie

Node實戰:運用Cookie&Session進行登入驗證

這是因為express-session會自動解析cookie和向前端設定cookie,相當於是圖一中的3、6(前半部:透過SessionId查詢到Session ,我們不再需要手動對cookie進行操作。

4️⃣ 權限驗證

#在登入成功時設定session

// controllers/UserController.js
// ....
// 登录校验
login: async (req, res, next) => {
   try {
       const { username, password } = req.body;
       const data = await UserService.login(username, password);
       // console.log(data);
       if (data) {
           // 设置session:向session对象内添加一个user字段表示当前登录用户
           req.session.user = data; // 默认存在内存中,服务器一重启就没了
           res.send({ ok: 1, msg: "登录成功!", data });
       } else {
           res.send({ ok: 0, msg: "用户不存在,登录失败!" });
       }
   } catch (error) {
       console.log(error);
   }
},

我們向req.session中新增了一個user字段,來保存使用者登入的信息,這一步相當於是圖一中的1(SessionId會由express-session 模組自動產生)、2

req.session是一個session對象,需要注意的是這個物件雖然存在於req中,但其實不同的人訪問系統時他們的req.session是不同的,因為req.session是根據我們設定的cookie(由 express-session模組自動產生的AilixUserSystem )產生的,每個人存取系統所產生的cookie是獨一無二的,所以他們的req .session也是獨一無二的。

在收到請求時校驗session,在app.js新增以下程式碼:

// 设置中间件:session过期校验
app.use((req, res, next) => {
    // 排除login相关的路由和接口
    // 这个项目中有两个,一个是/login的页面路由,一个是/api/login的post api路由,这两个路由不能被拦截
    if (req.url.includes("login")) {
        next();
        return;
    }
    if (req.session.user) {
        // session对象内存在user,代表已登录,则放行
        // 重新设置一下session,从而使session的过期时间重新计算(在session配置中配置了: resave: true)
        // 假如设置的过期时间为1小时,则当我12点调用接口时,session会在1点过期,当我12点半再次调用接口时,session会变成在1点半才会过期
        // 如果不重新计算session的过期时间,session则会固定的1小时过期一次,无论这期间你是否进行调用接口等操作
        // 重新计算session的过期时间的目的就是为了防止用户正在操作时session过期导致操作中断
        req.session.myData = Date.now();
        // 放行
        next();
    } else {
        // session对象内不存在user,代表未登录
        // 如果当前路由是页面路由,,则重定向到登录页
        // 如果当前理由是api接口路由,则返回错误码(因为针对ajax请求的前后端分离的应用请求,后端的重定向不会起作用,需要返回错误码通知前端,让前端自己进行重定向)
        req.url.includes("api")
            ? res.status(401).send({ msg: "登录过期!", code: 401 })
            : res.redirect("/login");
    }
});

注意:這段程式碼需要在路由配置的前面。

這段程式碼中我們透過req.session.myData = Date.now();來修改session對象,從而觸發session 過期時間的更新(sessionmyData這個屬性以及它的值Date.now()只是我們修改session物件的工具,本身是沒有任何意義的),你也可以使用其它方法,只要能將req.session修改即可。

因为我们这个项目是后端渲染模板的项目,并不是前后端分离的项目,所以在配置中间件进行session过期校验拦截路由时需要区分Api路由页面路由

后端在拦截API路由后,向前端返回错误和状态码:

Node實戰:運用Cookie&Session進行登入驗證

这个时候需要让前端自己对返回结果进行判断从而进行下一步的操作(如回到登录页或显示弹窗提示),该系统中前端是使用JavaScript内置的fetch来进行请求发送的,通过它来对每一个请求结果进行判断比较麻烦,大家可以自行改用axios,在axios的响应拦截器中对返回结果做统一的判断。

5️⃣ 退出登录

向首页(index.ejs)添加一个退出登录的按钮:

<button>退出登录</button>

为按钮添加点击事件:

const exit = document.getElementById('exit')

// 退出登录
exit.onclick = () => {
  fetch("/api/logout").then(res => res.json()).then(res => {
    if (res.ok) {
      location.href = "/login"
    }
  })
}

这里调用了GET /api/logout接口,现在定义一下这个接口,在controllers/UserController.js中定义接口的控制层(C层):

const UserController = {
 	// ......
    // 退出登录
    logout: async (req, res, next) => {
        // destroy方法用来清除cookie,当清除成功后会执行接收的参数(一个后调函数)
        req.session.destroy(() => {
            res.send({ ok: 1, msg: "退出登录成功!" });
        });
    },
};

routes/users.js中定义Api路由:

// 退出登录
router.get("/logout", UserController.logout);

6️⃣ 链接数据库

前面我们通过 req.session.user = data;设置的session默认是存放到内存中的,当后端服务重启时这些session就会被清空,为了解决这一问题我们可以将session存放到数据库中。

安装connect-mongo

npm i connect-mongo

connect-mongoMongoDB会话存储,用于用Typescript编写的连接Express

修改app.js

// 引入connect-mongo
var MongoStore = require("connect-mongo");

// 配置session
app.use(
    session({
        name: "AilixUserSystem", // cookie名字
        secret: "iahsiuhaishia666sasas", // 密钥:服务器生成的session的签名
        cookie: {
            maxAge: 1000 * 60 * 60, // 过期时间:一个小时过期
            secure: false, // 为true时表示只有https协议才能访问cookie
        },
        resave: true, // 重新设置session后会重新计算过期时间
        rolling: true, // 为true时表示:在超时前刷新时cookie会重新计时;为false表示:在超时前无论刷新多少次,都是按照第一次刷新开始计时
        saveUninitialized: true, // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活的信用卡
        store: MongoStore.create({
            mongoUrl: "mongodb://127.0.0.1:27017/usersystem_session", // 表示新建一个usersystem_session数据库用来存放session
            ttl: 1000 * 60 * 60, // 过期时间
        }), // 存放数据库的配置
    })
);

至此,我们就实现了运用Cookie&Session进行登录验证/权限拦截的功能!

更多node相关知识,请访问:nodejs 教程

以上是Node實戰:運用Cookie&Session進行登入驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:csdn。如有侵權,請聯絡admin@php.cn刪除
JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python還是JavaScript更好?Python還是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)