找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1583

积分

0

好友

228

主题
发表于 17 小时前 | 查看: 2| 回复: 0

在现代API开发中,用户认证是保障数据安全与访问控制的核心环节。对于许多从前端开发转向全栈的开发者而言,构建一套清晰、健壮且易于维护的认证体系是项目成功的关键。本文将基于真实项目,详细拆解在Node.js的Express框架中集成JWT(JSON Web Token)认证的完整实践,提供可复用的模板代码。

一、JWT核心概念解析

什么是JWT?

JWT是一种开放标准,用于在双方之间安全地传输信息。一个完整的JWT由三部分组成,以点号.分隔:Header.Payload.Signature

三个组成部分

  1. Header(头部):包含令牌类型(如JWT)和签名算法(如HS256)。
  2. Payload(载荷):存放需要传递的声明信息,如用户ID、角色。标准声明包括过期时间(exp)、签发者(iss)等。请注意,Payload内容仅是Base64编码,可以被解码,切勿存放密码等敏感信息。
  3. Signature(签名):由编码后的Header、Payload以及一个密钥(secret)通过指定算法生成,用于验证令牌在传输过程中是否被篡改。

JWT在副业项目中的优势

  • 无状态:服务端无需存储会话,减轻了服务器负担。
  • 扩展性好:天然支持移动端、Web端等多端登录。
  • 部署友好:与现代运维及容器化部署方案兼容性高。

二、项目集成准备

1. 安装依赖

首先,在项目根目录下安装jsonwebtoken库。

cd server
npm install jsonwebtoken

2. 环境变量配置

将密钥等敏感配置置于环境变量中,便于不同环境的管理。

# .env 文件
JWT_SECRET=your_super_secret_key_here
JWT_EXPIRES_IN=1h
  • JWT_SECRET:用于签名和验证Token的密钥,务必保证其复杂性与私密性。
  • JWT_EXPIRES_IN:定义Token的有效期,例如1h(1小时)、7d(7天)。

3. 统一定义业务错误码

config/codes.js等配置文件中,明确定义与认证相关的错误码,便于前后端协同。

// config/codes.js
module.exports = {
  UNAUTHORIZED: 401,   // 未授权/未登录
  TOKEN_EXPIRED: 402,  // Token过期
  // ... 其他错误码
};

三、登录流程:颁发Token

接口说明

  • 路径: POST /api/login
  • 功能: 验证用户凭证,成功后颁发JWT。

控制器实现 (authController.js)

const jwt = require('jsonwebtoken');
const codes = require('../config/codes');
const logger = require('../config/logger');

const login = (req, res) => {
  const { username, password } = req.body;

  // 1. 校验参数
  if (!username || !password) {
    return res.cc(null, '用户名或密码不能为空', codes.INVALID_PARAMS);
  }

  // 2. 校验用户凭证 (此处为示例,真实项目请查询数据库)
  if (username === 'testuser' && password === 'testpass') {
    const user = { id: 1, username: 'testuser', role: 'admin' };

    // 3. 生成JWT Token
    const token = jwt.sign(user, process.env.JWT_SECRET, {
      expiresIn: process.env.JWT_EXPIRES_IN,
    });

    logger.info(`用户 ${username} 登录成功,颁发 Token`);

    // 4. 返回Token及用户信息
    return res.cc(
      {
        token,
        user: { id: user.id, username: user.username, role: user.role },
      },
      '登录成功'
    );
  }

  logger.warn(`用户 ${username} 登录失败:账号或密码错误`);
  return res.cc(null, '用户名或密码错误', codes.UNAUTHORIZED);
};

module.exports = { login };

四、鉴权流程:校验Token

认证中间件实现

创建一个通用的auth中间件,用于保护需要登录态的路由。

// middleware/auth.js
const jwt = require('jsonwebtoken');
const codes = require('../config/codes');
const logger = require('../config/logger');

const auth = (req, res, next) => {
  // 1. 从请求头获取Token
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    logger.warn('未提供或格式错误的 Authorization Header');
    return res.cc(null, '访问未经授权,请提供 Token', codes.UNAUTHORIZED);
  }

  const token = authHeader.split(' ')[1]; // 提取真正的Token

  try {
    // 2. 验证并解码Token
    const decoded = jwt.verify(token, process.env.JWT_SECRET);

    // 3. 将用户信息挂载到请求对象上,供后续中间件或控制器使用
    req.user = decoded;
    logger.info(`Token 校验成功,用户ID:${decoded.id}`);
    next(); // 验证通过,继续执行下一个中间件或路由处理函数
  } catch (err) {
    // 4. 处理验证失败(过期或无效)
    if (err.name === 'TokenExpiredError') {
      return res.cc(null, 'Token 已过期,请重新登录', codes.TOKEN_EXPIRED);
    }
    logger.error(`Token 校验失败:${err.message}`);
    return res.cc(null, '无效 Token,请重新登录', codes.UNAUTHORIZED);
  }
};

module.exports = auth;

五、在路由中应用认证

在路由文件中,只需在需要保护的路由上引入auth中间件即可。

// routes/auth.js
const express = require('express');
const router = express.Router();
const { login } = require('../controllers/authController');
const auth = require('../middleware/auth');
const asyncHandler = require('../utils/asyncHandler');

// 公开路由:登录
router.post('/login', login);

// 受保护路由:需要有效Token才能访问
router.get(
  '/protected',
  auth, // 应用认证中间件
  asyncHandler(async (req, res) => {
    res.cc(
      {
        user: req.user, // 可以直接从req.user获取登录用户信息
        message: `欢迎你,用户ID:${req.user.id}`,
      },
      '访问受保护资源成功'
    );
  })
);

module.exports = router;

六、接口测试方法

1. 获取Token

使用POST请求调用登录接口。

POST /api/login
Content-Type: application/json

{
  "username": "testuser",
  "password": "testpass"
}

成功响应将包含token字段。

2. 访问受保护接口

在请求头中携带获取到的Token,访问受保护的接口。

GET /api/protected
Authorization: Bearer <your_token_here>

七、总结

通过上述步骤,我们构建了一套完整的Express JWT认证与授权体系。这套方案不仅实现了基础的登录鉴权,更提供了清晰的错误处理、日志记录和可扩展的用户信息管理,为后续添加角色权限控制(RBAC)等功能奠定了坚实的基础。其无状态特性、对前端友好的交互方式以及规范的代码结构,使其成为个人项目或中小型应用理想的认证解决方案。




上一篇:Linux与Windows平台FTP服务器搭建指南:vsftpd、IIS及FileZilla配置详解
下一篇:Flink Watermark机制源码深度解析:乱序数据处理与窗口触发原理
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 19:13 , Processed in 0.238044 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表