Node实战:运用Cookie&Session进行登录验证

Node实战:运用Cookie&Session进行登录验证

原文地址:https://ailjx.blog.csdn.net/article/details/127909213作者:海底烧烤店ai

在前面的几节中我们已经创建并优化好了简易用户管理系统的项目结构,也对 Cookie-Session登录验证 的工作原理做了讲解,接下来我们将继续补充这个系统的功能,这一节我们将实战运用Cookie-Session来实现这个系统的登录验证功能。【相关教程推荐:nodejs视频教程】

什么?你还不了解session、cookie!快去看看上篇文章吧:详解 Cookie-Session登录验证 的工作原理

1️⃣ 定义页面路由

在vies目录下新建login.ejs:

nbsp;html>                Document    

登录页面

    
用户名:
    
密码:
    
     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("用户名密码不匹配!") } }) }

登录后复制

注意:页面中请求的接口是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)添加一个退出登录的按钮:

登录后复制

为按钮添加点击事件:

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");// 配置sessionapp.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进行登录验证的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2697286.html

(0)
上一篇 2025年3月7日 18:41:04
下一篇 2025年3月3日 06:21:44

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 聊聊基于Node实现单点登录(SSO)的方法

    什么是单点登录?原理是什么?怎么实现?下面本篇文章带大家了解一下单点登录,并聊聊使用node实现单点登录sso的方法,希望对大家有所帮助! 【相关教程推荐:nodejs视频教程、编程教学】 什么是单点登录 随着公司业务的增多,必然会产生各个…

    2025年3月7日 编程技术
    200
  • 带你了解Nodejs中的非阻塞异步IO

    本篇文章带大家聊聊node中的各种i/o模型,介绍一下node的灵魂—非阻塞异步io,希望对大家有所帮助! 【相关教程推荐:nodejs视频教程、编程教学】 我们以网络请求IO为例,首先介绍服务端处理一次完整的网络IO请求的典型流程: 应用…

    2025年3月7日 编程技术
    200
  • 手把手带你从0开始创建并发布npm包

    都2202年了,不会有人还不会发布npm包吧?下面本篇文章给大家分享一下从0开始创建并发布npm的全过程,希望对大家有所帮助! 背景 4月发布了一篇文章,快来升级你项目内的axios封装,向重复请求say goodbye,介绍了axios的…

    2025年3月7日 编程技术
    200
  • 一文带你深入了解Node中的Buffer类

    本篇文章带大家深入了解下node中 buffer(缓冲区)类,希望对大家有所帮助! 在TypedArray出来之前,JavaScript这门语言是不能很好地处理原始二进制数据(raw binary data)的,这是因为一开始的时候Java…

    2025年3月7日
    200
  • 聊聊如何选择一个最好的Node.js Docker镜像?

    选择一个node的docker镜像看起来像是一件小事,但是镜像的大小和潜在漏洞可能会对你的ci/cd流程和安全造成重大的影响。那我们如何选择一个最好node.js docker镜像呢? 我们在使用FROM node:latest或只是FRO…

    2025年3月7日
    200
  • 一文聊聊node中的path模块

    path 模块是 nodejs 中用于处理文件/目录路径的一个内置模块,可以看作是一个工具箱,提供诸多方法供我们使用,当然都是和路径处理有关的。同时在前端开发中 path 模块出现的频率也是比较高的,比如配置 webpack 的时候等。本文…

    2025年3月7日
    200
  • 实战学习:聊聊Node.js怎么操作数据库

    本篇文章分享node.js服务端实战,介绍一下node操作数据库的方法,希望对大家有所帮助! 本系列是使用node作为服务器开发的操作过程记录,记录一下主要的内容并且整理过程的脉络,以初学者的方式将学习内容记录下来,从0到1逐步的学习nod…

    2025年3月7日 编程技术
    200
  • 一文详解多版本node的安装和管理

    本篇文章带大家聊聊多版本node的管理,介绍一下多版本node的安装与切换详细操作,希望对大家有所帮助! 安装多版本node的原因: 在项目开发过程中,不同项目使用的nodejs版本不同,有时会因为node版本过高或太低,导致报错;如何在同…

    2025年3月7日 编程技术
    200
  • 一文聊聊Node包管理发展的五个阶段

    从2009年 node 诞生至今,node 生态发展繁荣,围绕 node 生态衍生出的 node 包管理器百花齐放,先后出现了 npm、kpm、pnpm、yarn、cnpm 等等。实际上 node 包管理器发展主要分5个阶段,下面我们一起看…

    2025年3月7日 编程技术
    200
  • 一文详解Nodejs怎么卸载(步骤分享)

    node怎么卸载?下面本篇文章给大家分享一下node卸载超详细步骤,有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 Node卸载超详细步骤 1、打开系统的控制面板,点击卸载程序,卸载nodejs 【相关教程推荐:node、…

    2025年3月7日 编程技术
    200

发表回复

登录后才能评论