0


Node.js | Express+MongoDB 实现简易用户管理系统(三)(登录验证之Cookie&Session)

在这里插入图片描述


🧑‍💼 个人简介:一个不甘平庸的平凡人🍬
🖥️ 本系列专栏:Node.js从入门到精通
🖥️ TS知识总结:十万字TS知识点总结
👉 你的一键三连是我更新的最大动力❤️!
📢 欢迎私信博主加入前端交流群🌹


📑目录


🔽 前言

在前面的几节中我们已经创建并优化好了简易用户管理系统的项目结构,也对

Cookie-Session登录验证

的工作原理做了讲解,接下来我们将继续补充这个系统的功能,这一节我们将实战运用

Cookie-Session

来实现这个系统的登录验证功能。

什么?你还不了解

session

cookie

!快去看看上篇文章吧:详解 Cookie-Session登录验证 的工作原理

1️⃣ 定义页面路由

vies

目录下新建

login.ejs

<!DOCTYPE html><html lang="en"><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>登录页面</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('/api/login',{method:'POST',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

正常显示:

在这里插入图片描述

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);

至此登录页面就搭建好了:

在这里插入图片描述

3️⃣ 配置session

在上一节

Cookie-Session

登录验证工作原理的介绍中我们知道:

图一

图一

这个过程显然是比较复杂的,在

express

中有一个

express-session

模块可以大大降低我们的工作量,让我们站在巨人的肩膀上开发!

下载

express-session

npm i express-session

app.js

中进行配置:

// 引入express-sessionvar 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是无效的,相当于是没有激活的信用卡}));

配置好后,就会发现浏览器中有一个名为

AilixUserSystem

cookie

在这里插入图片描述

这是因为

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

过期时间的更新(

session

myData

这个属性以及它的值

Date.now()

只是我们修改

session

对象的工具,其本身是没有任何意义的),你也可以使用其它方法,只要能将

req.session

修改即可。

因为我们这个项目是后端渲染模板的项目,并不是前后端分离的项目,所以在配置中间件进行

session

过期校验拦截路由时需要区分

Api路由

页面路由

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

在这里插入图片描述

这个时候需要让前端自己对返回结果进行判断从而进行下一步的操作(如回到登录页或显示弹窗提示),该系统中前端是使用

JavaScript

内置的

fetch

来进行请求发送的,通过它来对每一个请求结果进行判断比较麻烦,大家可以自行改用

axios

,在

axios

的响应拦截器中对返回结果做统一的判断。

5️⃣ 退出登录

向首页(

index.ejs

)添加一个退出登录的按钮:

<buttonid="exit">退出登录</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-mongo是MongoDB会话存储,用于用

Typescript编写的连接

Express

修改

app.js

// 引入connect-mongovar 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数据库用来存放sessionttl:1000*60*60,// 过期时间}),// 存放数据库的配置}));

至此,我们就实现了运用

Cookie&Session

进行登录验证/权限拦截的功能!

🔼 结语

博主的Node.js从入门到精通专栏正在持续更新中,关注博主订阅专栏学习Node不迷路!

如果本篇文章对你有所帮助,还请客官一件四连!❤️

📢 欢迎私信博主加入前端交流群🌹

在这里插入图片描述

标签: node.js express mongodb

本文转载自: https://blog.csdn.net/m0_51969330/article/details/127909213
版权归原作者 海底烧烤店ai 所有, 如有侵权,请联系我们删除。

“Node.js | Express+MongoDB 实现简易用户管理系统(三)(登录验证之Cookie&Session)”的评论:

还没有评论