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

Next.js 14(App Router)自定义.NET后端认证两大问题求助

解决方案建议

问题一:令牌刷新后Local Storage的Access Token同步问题

方案1:刷新时主动更新Local Storage

在调用刷新令牌的API逻辑里,拿到新的Access Token后直接执行Local Storage更新操作。比如:

const refreshToken = async () => {
  const response = await fetch('/api/refresh-token', {
    method: 'POST',
    credentials: 'include' // 携带Cookie中的Refresh Token
  });
  const data = await response.json();
  if (data.accessToken) {
    localStorage.setItem('accessToken', data.accessToken);
  }
};

如果你的刷新逻辑封装在Axios拦截器这类全局请求处理中,就在响应拦截部分,检测到401并成功刷新令牌后,同步更新Local Storage。

方案2:移除Local Storage存储,改用HttpOnly Cookie(推荐)

Local Storage存Access Token存在XSS攻击风险,更安全的做法是把Access Token也存入HttpOnly Cookie。后端刷新令牌后会自动更新Cookie,前端无需处理同步问题,API请求时浏览器会自动携带Cookie,后端直接验证即可。

修改认证成功后的逻辑:仅将Access Token、Refresh Token、用户信息存入HttpOnly Cookie,不再写入Local Storage。前端发起API请求时,确保请求带上credentials: 'include'(或same-origin,根据跨域配置调整)。

问题二:路由保护中间件的严谨性优化

当前仅检查Cookie存在远远不够,需要验证Token的有效性,具体实现步骤如下:

  1. 安装JWT验证库(若使用JWT令牌)
    安装支持Edge Runtime的jose库:
npm install jose
  1. 编写Middleware逻辑
    在项目根目录的middleware.ts中实现Token验证:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { jwtVerify } from 'jose';

export async function middleware(request: NextRequest) {
  // 从Cookie获取Access Token
  const accessToken = request.cookies.get('accessToken')?.value;
  const protectedPaths = ['/dashboard', '/profile']; // 你的受保护路由列表

  // 访问受保护路由但无Token,重定向至登录页
  if (protectedPaths.some(path => request.nextUrl.pathname.startsWith(path)) && !accessToken) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  if (accessToken) {
    try {
      // 验证JWT签名与过期时间,替换为你的后端公钥
      const secret = new TextEncoder().encode(process.env.JWT_SECRET!);
      await jwtVerify(accessToken, secret);
      // 验证通过,放行请求
      return NextResponse.next();
    } catch (error) {
      // Token无效,尝试刷新
      const refreshToken = request.cookies.get('refreshToken')?.value;
      if (!refreshToken) {
        // 无Refresh Token,重定向登录
        return NextResponse.redirect(new URL('/login', request.url));
      }

      // 调用后端刷新接口
      const refreshResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/refresh`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ refreshToken }),
        credentials: 'include'
      });

      if (refreshResponse.ok) {
        const data = await refreshResponse.json();
        // 更新Cookie中的Access Token
        const response = NextResponse.next();
        response.cookies.set('accessToken', data.accessToken, {
          httpOnly: true,
          secure: process.env.NODE_ENV === 'production',
          sameSite: 'strict',
          maxAge: 3600 // 与后端保持一致的有效期
        });
        return response;
      } else {
        // 刷新失败,重定向登录
        return NextResponse.redirect(new URL('/login', request.url));
      }
    }
  }
}

// 指定需要经过Middleware的路由
export const config = {
  matcher: ['/dashboard/:path*', '/profile/:path*']
};

注意事项

  • 确保后端JWT公钥/密钥正确配置在环境变量中
  • 刷新令牌接口需验证Refresh Token有效性,并返回新的Access Token
  • Middleware运行在Edge Runtime,避免使用Node.js专属API

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:53:22