Node登陆认证实战!10分钟手把手教会你!

0.前言

在企业级开发中,Token 认证机制已成为保护 API 安全的行业标准。

本文将演示如何通过 Node.js 生成 JSON Web Token (JWT),并结合 Redis 缓存实现完整的认证流程。

1.安装工具库

  • express:Express 的作用相当于 node.js 的内置模块 http,是专门用来创建web服务器的。用来接收前端的请求。
  • jsonwebtoken:生成、校验 token 的工具。
  • ioredis:缓存数据的工具,对 redis 插件进行封装,集成 promise 等工具。
  • dotenv:用来管理本地环境变量。
  • mysql2:操作数据库
  • sequelize:封装数据库操作,通过内置 api 而不是sql语句操作数据库。
css 复制代码
npm install express jsonwebtoken ioredis dotenv mysql2  sequelize

2.配置环境

在项目根目录新建 .env 文件

在 app.js 中配置 dotenv

css 复制代码
require('dotenv').config();

然后我们就可以在项目中自定义的文件中获取 .env 文件中配置的数据了,例如:

css 复制代码
process.env.REDIS_PORT

3.配置 redis

Redis 是一个高性能的键值存储数据库,常用于缓存、消息队列、会话存储等场景。

在 Node.js 中使用 Redis 可以显著提升应用性能,尤其是在频繁读取数据的场景下。

如果你是前端小白,这里你就把 Redis 当成一个很牛逼的数据库,可以存各式各样的数据,可以给存储的数据设置过期时间,时间一到就自动删除了。

Redis 和 MySQL 数据库一样,分为服务端和客户端。服务端用来存储数据,客户端用来对数据进行读写操作。

所以我们要先安装服务端,再安装客户端。

安装 Redis 服务端的文章大家可以自行搜索,或者去问 DeepSeek、豆包等大模型,这里不再赘述。

而本文我们安装的 ioredis 是一个 Node.js 环境下的 Redis 客户端库。我们可以通过它内置的 API 操作 Redis 数据库中的数据。

3.1 配置 Redis

新建 config 文件夹,然后新建 redis.js 文件:

将创建好的 Redis 配置文件加载到 app.js 中

4.jwt 生成 token

古代调兵遣将需要兵符,这个兵符就是个凭证,凭证为真,兵部才允许你把兵调走。

同样在系统开发中,只有是这个系统的用户才被允许访问一些资源。

1.前端用户登陆成功之后,后台通过一个工具将一段字符串返回给前端用户。

2.前端用户每次访问其他页面(资源)的时候请求头都携带这个字符串。

3.后端拿到这个字符串之后再用工具去校验,校验通过,就允许访问其他资源。

所以我们说的字符串就是 token,只不过这个字符串比较复杂。

而JWT是一种具体的 Token 实现方式,是一种认证解决方案。

你可以把 token 看做是 JWT。

而项目中我们安装的 jsonwebtoken 是一个生成 token 字符串、校验 token 的工具。比如它的生成 token 的方法:

css 复制代码
jwt.sign(
    user,// Payload
    JWT_SECRET, // 秘钥   
    { expiresIn: "1h" } // 令牌过期时间(1小时)  
  );

所以 JWT 由三部分组成,用点号(.)分隔:

  • Header(头部):包含令牌的类型和签名算法。
  • Payload(载荷):包含声明(Claims),即关于用户或其他实体的信息。
  • Signature(签名):用于验证令牌的完整性和真实性。 一个典型的 JWT 看起来像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaGFuIEdvZGxleSIsImlhdCI6MTUxNjIzOTAzMCwiZXhwIjoxNTE2MjM5MDkwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

也就是使用 jsonwebtoken 库的 sign 方法就能生成一个 token 字符串。

前面说了一堆废话,接下来配置 jwt 工具:在 utils 文件夹在新建 jwt.js 文件

在 app.js 文件中加载 jwt

注:jsonwebtoken 设置 token 过期时间有两种方式:

1.数值,1小时是60x60x1000=3600000

css 复制代码
const token = jwt.sign(
    { id: user.id, },// Payload
    process.env.JWT_SECRET, // 秘钥   
    { expiresIn: 3600000 }
  );

2.字符串: 1h表示1小时,2m表示2分钟,24d表示24天

css 复制代码
const token = jwt.sign(
    { id: user.id, },// Payload
    process.env.JWT_SECRET, // 秘钥   
   { expiresIn: "1h" }
  );

5.改造用户登陆接口

核心流程:

  • 1.获取请求参数:username 和 password
  • 2.使用 sequelize 的 findOne 方法查询用户信息。注:sequelize 工具的使用在前面几篇文章讲的有,这里不再赘述。
  • 3.如果用户不存在,返回错误信息。
  • 4.用户存在,密码不对,返回错误信息
  • 5.生成 token 信息
  • 6.将token信息存储到 redis,设置过期时间
  • 7.将token返回给前端
css 复制代码
// 用户登陆
router.post('/login', async (req, res) => {
  try {
    const { username, password } = req.body;
    // 根据用户名查询用户信息
    const user = await User.findOne({
      where: {
        username: username,
      }
    });
    // 用户存在
    if (user) {
      // 校验密码
      if (password != user.password) {
        throw new CustomError("密码错误!");
      }
      // 生成token
      const token = generateToken(user);
      // 将token存储到Redis
      await redisClient.set(`token:${user.id}`, token, 'EX', 3600); // 1小时过期
      // 将token返回
      const result = { token: token };
      success(res, "登录成功", result);
    } else {
      throw new CustomError("用户不存在!");
    }
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

注:redis 存储数据的方法:

  • 参数1:key
  • 参数2:value
  • 参数3:固定,表示设置过期时间
  • 参数4:过期时间具体值,3600表示 1 小时,和jwt不一样
vbnet 复制代码
redisClient.set(key, value, 'EX', 过期时间)

测试结果:

密码错误

登陆成功,返回 token 信息

6.Token 身份校验

在 utils 文件夹下新建 auth.js 文件:

核心流程:

  • 1.从请求头中获取 token 信息,如果 token 不存在,就返回错误信息
  • 2.使用 jsonwebtoken 库的 verify 方法校验 token 信息,校验失败返回错误信息
  • 3.从Redis缓存中获取 token 信息,如果 token 不存在,就返回错误信息
  • 4.校验成功,才能访问其他资源

然后在需要进行安全校验的接口上面添加这个方法:

测试:

1.header 为空

2.token校验失败

3.token校验成功

7.完整代码

css 复制代码
通过网盘分享的文件:zhifou-mall-node-api.zip
链接: https://pan.baidu.com/s/10zOgKQiNfBIrppfAUk6lpw?pwd=6666 
提取码: 6666 

拿到代码之后记得:

  • npm install 安装依赖
  • 修改 Sequelize.js 里面连接 MySQL 数据库的账号密码等配置项
  • 修改 .env 文件 redis 的配置信息
  • npm app.js 启动后端项目
相关推荐
Huazie40 分钟前
在WSL2 Ubuntu中部署FastDFS服务的完整指南
服务器·后端·ubuntu
行者无疆xcc2 小时前
【Django】设置让局域网内的人访问
后端·python·django
嘵奇2 小时前
基于Spring Boot实现文件秒传的完整方案
java·spring boot·后端
Value_Think_Power2 小时前
azure 一个 pod 内有多个 container ,这些container 可以 共享一块磁盘吗
后端
李菠菜2 小时前
优化Centos关闭SELinux/Swap及资源限制调整
linux·后端·centos
wangyongquan2 小时前
koa语法 | koa/router | 中间件 | 洋葱模型
后端·node.js
小兵张健2 小时前
小米 JD 调研
java·后端·面试
BigTopOne2 小时前
【君正-T41】外设采集h264流程
后端
caihuayuan52 小时前
JavaScript数据结构与算法实战: 探秘Leetcode经典题目
java·大数据·spring boot·后端·课程设计
日日行不惧千万里2 小时前
Node.js和js到底什么关系
开发语言·javascript·node.js