掌握 JWT 身份验证:MERN Stack 完整指南

身份验证是 Web 应用程序的核心方面,可确保安全访问敏感数据和服务。**JSON Web Token (JWT)** 是现代 Web 应用程序中实现身份验证的最流行方法之一。它轻量级、安全,是全栈应用程序中无状态身份验证的理想选择。

在本指南中,我们将通过实际示例探索 JWT、其结构、优势以及在 MERN(MongoDB、Express.js、React.js、Node.js)堆栈中的实现。

什么是 JSON Web Token (JWT)?

**JWT** 是一个开放标准 (RFC 7519),用于以 JSON 对象的形式在双方(客户端和服务器)之间安全地传输信息。令牌经过数字签名,可确保其真实性。

JWT 的结构

JWT 由三部分组成:

  • 标头:包含有关令牌的元数据,例如用于签名的算法(例如,HS256)。
  • 有效负载:包含声明(数据),例如用户 ID、角色和到期时间。
  • 签名:标头和有效负载的加密哈希,用于验证令牌的完整性。
  • 其结构表示为:

    Header.Payload.Signature

    JWT 示例

    以下是 JWT 的一个示例:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6InVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    为什么在 MERN 应用程序中使用 JWT?

  • 无状态身份验证:JWT 允许服务器保持无状态,因为它将所有身份验证数据存储在客户端。
  • 可扩展性:非常适合分布式系统,因为不需要会话存储。
  • 安全性:提供加密并确保数据传输防篡改。
  • 跨平台兼容性:可跨多个框架和环境运行。
  • 在 MERN 堆栈中实现 JWT 身份验证

    按照以下步骤将 JWT 集成到 MERN 应用程序中:

    步骤 1:后端 - 设置 Express.js 和 JWT

    安装所需的软件包

    npm install express jsonwebtoken bcryptjs mongoose dotenv cors

    代码示例:后端(Node.js 和 Express.js)

    **创建 JWT 并在登录和注册时验证它。**

  • 生成 JWT 令牌
  • const jwt = require('jsonwebtoken');
    const SECRET_KEY = "your_secret_key";
    
    // Function to generate a token
    const generateToken = (user) => {
      const payload = { id: user._id, email: user.email };
      return jwt.sign(payload, SECRET_KEY, { expiresIn: '1h' });
    };
  • 使用中间件保护路由
  • const authenticateToken = (req, res, next) => {
      const token = req.headers['authorization']?.split(' ')[1];
      if (!token) return res.status(401).json({ message: "Access Denied" });
    
      jwt.verify(token, SECRET_KEY, (err, user) => {
        if (err) return res.status(403).json({ message: "Invalid Token" });
        req.user = user;
        next();
      });
    };
    
    // Example of a protected route
    app.get('/dashboard', authenticateToken, (req, res) => {
      res.json({ message: "Welcome to the dashboard!", user: req.user });
    });
  • 用于安全存储的哈希密码
  • const bcrypt = require('bcryptjs');
    
    const hashPassword = async (password) => {
      const salt = await bcrypt.genSalt(10);
      return await bcrypt.hash(password, salt);
    };
    
    const comparePasswords = async (password, hashedPassword) => {
      return await bcrypt.compare(password, hashedPassword);
    };

    第 2 步:前端 - React.js 集成

    安装 Axios

    npm install axios

    代码示例:React.js(使用 JWT 的登录表单)

  • 发送登录请求
  • import axios from 'axios';
    
    const loginUser = async (email, password) => {
      try {
        const response = await axios.post('http://localhost:5000/login', { email, password });
        const token = response.data.token;
    
        // Store token in localStorage
        localStorage.setItem('token', token);
    
        console.log('Login Successful', token);
      } catch (error) {
        console.error('Login Failed', error.response.data.message);
      }
    };
  • 访问受保护的数据
  • const fetchProtectedData = async () => {
      const token = localStorage.getItem('token');
      try {
        const response = await axios.get('http://localhost:5000/dashboard', {
          headers: { Authorization: `Bearer ${token}` },
        });
        console.log('Protected Data:', response.data);
      } catch (error) {
        console.error('Access Denied', error.response.data.message);
      }
    };

    步骤 3:安全令牌存储和到期处理

  • 安全存储令牌:使用 localStorage 或 sessionStorage 存储令牌。避免以纯文本形式存储敏感数据。
  • 处理令牌过期:定期检查令牌有效性。如果过期,则提示用户重新进行身份验证。
  • 例子:

    const isTokenExpired = (token) => {
      const decoded = jwt.decode(token);
      return decoded.exp * 1000 < Date.now();
    };

    JWT 的优点和局限性

    优点

  • 无状态且可扩展
  • 支持跨域资源共享(CORS)
  • 易于集成到 RESTful API
  • 限制

  • 与基于会话的 Cookie 相比,令牌大小更大
  • 除非使用过期,否则令牌不能失效
  • 使用 JWT 的最佳实践

  • 使用 HTTPS:始终加密通信以防止令牌拦截。
  • 确保秘密安全:安全地存储密钥(例如,环境变量)。
  • 设置到期时间:限制令牌的有效性以降低风险。
  • 使用刷新令牌:对于长寿命会话,发出刷新令牌。
  • MERN 中 JWT 的有用库

  • jsonwebtoken:用于生成和验证 token
  • bcrypt.js:用于密码哈希处理
  • express-jwt:用于保护 API 路由
  • 终于

    JWT 是一款功能强大的工具,可用于在 MERN 堆栈应用程序中实现安全且可扩展的身份验证。通过了解其结构、优势和最佳实践,您可以高效地构建强大、安全的 Web 应用程序。按照本指南操作,您将能够顺利掌握 MERN 中的 JWT 身份验证。

    祝你编码愉快!