You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS中JWT认证遇难题:边缘运行时无法读取公钥求方案

解决Next.js中间件中RS256 JWT验证的公钥读取问题

不用单独搭建Express应用,Next.js本身就能解决这个问题,以下是几个可行的方案:

方案一:将公钥嵌入环境变量

RS256的公钥是PEM格式的文本,可以直接将其转成单行格式(把换行符替换为\n)后存入环境变量,中间件直接调用即可。

操作步骤:

  • 打开你的公钥文件,复制全部内容,把换行符替换为\n,比如将:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
...
-----END PUBLIC KEY-----

转换为:
"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...\n...\n-----END PUBLIC KEY-----"

  • 将转换后的值存入.env.local的JWT_PUBLIC_KEY变量中
  • 中间件中直接使用(推荐用jose库,它适配边缘运行时,无需Node.js的fs模块):
import { jwtVerify } from 'jose';
import { NextResponse } from 'next/server';

export async function middleware(request) {
  const token = request.cookies.get('token')?.value;
  if (!token) return NextResponse.redirect(new URL('/login', request.url));

  const publicKey = new TextEncoder().encode(process.env.JWT_PUBLIC_KEY);
  try {
    await jwtVerify(token, publicKey, { algorithms: ['RS256'] });
    return NextResponse.next();
  } catch (err) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

方案二:构建时嵌入公钥到代码

利用Next.js的构建时能力,提前读取公钥并生成一个常量文件,中间件直接导入该文件即可。

操作步骤:

  • 新建脚本文件scripts/generate-public-key.js:
const fs = require('fs');
const path = require('path');

const publicKey = fs.readFileSync(path.join(__dirname, '../public-key.pem'), 'utf8');
fs.writeFileSync(path.join(__dirname, '../app/public-key.js'), `export const PUBLIC_KEY = \`${publicKey}\`;`);
  • 修改package.json的构建命令,在构建前执行该脚本:
"scripts": {
  "prebuild": "node scripts/generate-public-key.js",
  "build": "next build",
  "dev": "next dev"
}
  • 中间件中导入使用:
import { PUBLIC_KEY } from './public-key';
import { jwtVerify } from 'jose';
import { NextResponse } from 'next/server';

export async function middleware(request) {
  const token = request.cookies.get('token')?.value;
  if (!token) return NextResponse.redirect(new URL('/login', request.url));

  const publicKey = new TextEncoder().encode(PUBLIC_KEY);
  try {
    await jwtVerify(token, publicKey, { algorithms: ['RS256'] });
    return NextResponse.next();
  } catch (err) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

这个方案避免了公钥暴露在环境变量中,构建时直接将公钥嵌入代码,边缘运行时可直接读取。

方案三:改用HS256对称加密(业务场景允许时)

如果你的业务不需要非对称加密的特性(比如无需区分签名和验证的密钥权限),可以直接切换到HS256算法。将密钥存入环境变量,验证时直接使用该密钥即可,这种方式最简便,完全适配边缘运行时。

注意:HS256的密钥需要严格保密,因为签名和验证使用同一个密钥,一旦泄露就可能被伪造令牌。

为什么不需要单独搭建Express?

Next.js的API路由本身就能处理JWT生成逻辑,中间件负责请求拦截和验证,整套流程可以在Next.js内部完成,额外搭建Express只会增加系统复杂度,没有必要。

内容的提问来源于stack exchange,提问作者Some Guy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 09:06:30