跳转到内容

Next.js JWT认证

来自代码酷

Next.js JWT认证[编辑 | 编辑源代码]

介绍[编辑 | 编辑源代码]

JSON Web Token (JWT) 是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为 JSON 对象。在 Next.js 中,JWT 常用于身份验证和授权,允许服务器验证客户端请求的合法性。JWT 由三部分组成:头部(Header)、载荷(Payload)和签名(Signature),通常以以下形式呈现: 解析失败 (语法错误): {\displaystyle JWT = Base64URL(Header) + "." + Base64URL(Payload) + "." + Signature}

JWT 的主要优势包括:

  • 无状态:服务器不需要存储会话信息,所有必要数据都包含在令牌中。
  • 跨域支持:适用于分布式系统和微服务架构。
  • 安全性:使用签名或加密确保数据完整性。

JWT 结构[编辑 | 编辑源代码]

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

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1. 头部(Header)[编辑 | 编辑源代码]

包含令牌类型和签名算法,例如:

{
  "alg": "HS256",
  "typ": "JWT"
}

2. 载荷(Payload)[编辑 | 编辑源代码]

包含声明(claims),即用户数据和其他元数据。例如:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

3. 签名(Signature)[编辑 | 编辑源代码]

使用密钥对头部和载荷进行签名,确保数据未被篡改。例如(使用 HMAC SHA256):

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

在 Next.js 中实现 JWT 认证[编辑 | 编辑源代码]

安装依赖[编辑 | 编辑源代码]

首先安装必要的库:

npm install jsonwebtoken cookie

生成 JWT[编辑 | 编辑源代码]

以下是一个生成 JWT 的示例:

const jwt = require('jsonwebtoken');

function generateToken(user) {
  return jwt.sign(
    { userId: user.id, email: user.email },
    process.env.JWT_SECRET,
    { expiresIn: '1h' }
  );
}

验证 JWT[编辑 | 编辑源代码]

验证 JWT 的中间件示例:

const jwt = require('jsonwebtoken');

function authenticateToken(req, res, next) {
  const token = req.cookies.token;
  if (!token) return res.sendStatus(401);

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
}

在 API 路由中使用[编辑 | 编辑源代码]

保护 API 路由的示例:

export default function handler(req, res) {
  if (req.method !== 'GET') return res.status(405).end();
  
  authenticateToken(req, res, () => {
    res.json({ message: 'Protected data', user: req.user });
  });
}

实际应用场景[编辑 | 编辑源代码]

用户登录流程[编辑 | 编辑源代码]

sequenceDiagram participant Client participant Server Client->>Server: 提交用户名/密码 Server->>Server: 验证凭证 Server->>Client: 返回JWT (Set-Cookie) Client->>Server: 包含JWT的请求 (Cookie) Server->>Server: 验证JWT Server->>Client: 返回受保护数据

代码示例:登录处理[编辑 | 编辑源代码]

import jwt from 'jsonwebtoken';
import { serialize } from 'cookie';

export default function loginHandler(req, res) {
  const { email, password } = req.body;
  
  // 验证用户(简化示例)
  const user = users.find(u => u.email === email && u.password === password);
  if (!user) return res.status(401).json({ error: 'Invalid credentials' });

  // 生成JWT
  const token = jwt.sign(
    { userId: user.id },
    process.env.JWT_SECRET,
    { expiresIn: '1h' }
  );

  // 设置HTTP-only Cookie
  const serialized = serialize('token', token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
    maxAge: 60 * 60,
    path: '/',
  });

  res.setHeader('Set-Cookie', serialized);
  res.status(200).json({ message: 'Login successful' });
}

安全最佳实践[编辑 | 编辑源代码]

1. 使用HTTPS:始终在生产环境中使用HTTPS传输JWT 2. 设置合理的过期时间:避免使用过长的有效期 3. HTTP-only Cookies:防止XSS攻击 4. CSRF保护:使用SameSite属性和CSRF令牌 5. 密钥管理:使用强密钥并定期轮换

常见问题[编辑 | 编辑源代码]

JWT vs Session Cookies[编辑 | 编辑源代码]

特性 JWT Session Cookies
状态管理 无状态 服务器端状态
存储位置 客户端 通常为HTTP-only Cookie
跨域支持 有限制
数据大小 受Cookie大小限制 无限制(服务器端)

JWT 安全考虑[编辑 | 编辑源代码]

  • 不要存储敏感信息在JWT中
  • 使用适当的算法(如HS256或RS256)
  • 实现令牌撤销机制(黑名单)

进阶主题[编辑 | 编辑源代码]

刷新令牌[编辑 | 编辑源代码]

实现长期会话的常见模式:

// 生成访问令牌和刷新令牌
function generateTokens(user) {
  const accessToken = jwt.sign(
    { userId: user.id },
    process.env.ACCESS_TOKEN_SECRET,
    { expiresIn: '15m' }
  );
  
  const refreshToken = jwt.sign(
    { userId: user.id },
    process.env.REFRESH_TOKEN_SECRET,
    { expiresIn: '7d' }
  );
  
  return { accessToken, refreshToken };
}

无状态权限控制[编辑 | 编辑源代码]

在JWT中嵌入角色信息:

{
  "userId": 123,
  "roles": ["admin", "editor"],
  "iat": 1516239022,
  "exp": 1516242622
}

总结[编辑 | 编辑源代码]

JWT 为 Next.js 应用提供了一种灵活、安全的身份验证机制。通过正确实现和遵循安全最佳实践,开发者可以构建健壮的认证系统。记住要根据应用的具体需求选择适当的策略,并始终优先考虑安全性。