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

Next.js中客户端如何借助Http-only Cookie实现认证请求?

问题:从CRA迁移到Next.js后,Http-only Cookie存储的JWT如何在客户端请求中使用?

之前在CRA项目里,JWT存储在localStorage中,可直接添加到请求头Authorization: 'Bearer ...'里完成认证。现在按照Next.js的安全推荐,把令牌存在Http-only Cookie中,但客户端创建的请求实例(如axios、RTK Query)无法直接读取这个Cookie,请问如何正确代表已认证用户发送请求?

附登录API路由代码(api/auth/login/route.ts):

import { NextResponse } from 'next/server';
import axios from 'axios';

export async function POST(request: Request) {
  const { token } = await request.json();

  try {
    const { data }: { data: OAuthResponse } = await axios.post(
      `${process.env.NEXT_PUBLIC_AXIOS_BASE_DEV_URL}auth/by-google`,
      { token }
    );

    const response = NextResponse.json({ success: true });

    response.cookies.set('auth_token', data.token, {
      httpOnly: true,
      secure: true,
      maxAge: 30 * 24 * 60 * 60,
      path: '/',
    });

    return response;
  } catch (error) {
    return NextResponse.json(
      { message: 'Authorization failed' },
      { status: 401 }
    );
  }
}

附RTK Query切片代码:

export const authApi = createApi({
  reducerPath: 'api/auth',
  baseQuery: ...,
  endpoints: (build) => ({
    loginWithGoogle: build.mutation<OAuthResponse, OAuthRequest>({
      query: (body) => ({
        url: 'auth/by-google',
        method: 'POST',
        body,
      }),
    }),
    fetchMe: build.query<OAuthResponse, void>({
      query: () => ({
        url: 'auth/me',
        method: 'GET',
      }),
    }),
  }),
});

不想使用next-auth这类第三方库,希望了解Next.js原生实现方式。


解决方案

方案1:通过Next.js API路由代理请求(推荐)

Http-only Cookie仅能被服务器端读取,因此可以在Next.js中编写API代理路由,客户端请求该代理路由后,由服务器端读取Cookie并添加到请求头,再转发给后端接口。

步骤:

  1. 创建代理API路由,比如api/proxy/[...path]/route.ts:
import { NextResponse } from 'next/server';
import axios from 'axios';

// 处理GET请求,同理可扩展POST/PUT等方法
export async function GET(request: Request) {
  // 从请求中读取Http-only Cookie
  const authToken = request.cookies.get('auth_token')?.value;
  if (!authToken) {
    return NextResponse.json({ message: 'Unauthorized' }, { status: 401 });
  }

  // 解析请求路径,拼接后端目标地址
  const url = new URL(request.url);
  const targetPath = url.pathname.replace('/api/proxy/', '');
  const targetUrl = `${process.env.NEXT_PUBLIC_AXIOS_BASE_DEV_URL}${targetPath}`;

  try {
    const response = await axios.get(targetUrl, {
      headers: {
        Authorization: `Bearer ${authToken}`,
      },
    });
    return NextResponse.json(response.data);
  } catch (error) {
    return NextResponse.json(
      { message: 'Request failed' },
      { status: (error as any)?.response?.status || 500 }
    );
  }
}
  1. 修改RTK Query的baseQuery,指向代理路由:
import { fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const baseQuery = fetchBaseQuery({
  baseUrl: '/api/proxy/',
});

export const authApi = createApi({
  reducerPath: 'api/auth',
  baseQuery,
  endpoints: (build) => ({
    fetchMe: build.query<OAuthResponse, void>({
      query: () => ({
        url: 'auth/me',
        method: 'GET',
      }),
    }),
  }),
});

这种方式完全符合Http-only Cookie的安全设计,所有认证逻辑由服务器端处理,客户端无需接触令牌。

方案2:客户端直接请求后端(需配置CORS)

如果不想使用代理,只要后端配置了正确的CORS策略,浏览器会自动将Http-only Cookie随请求发送给后端,无需客户端手动读取。

步骤:

  1. 后端配置CORS,允许携带凭证:
    以Node.js/Express为例,设置:

    const cors = require('cors');
    app.use(cors({
      credentials: true,
      origin: process.env.NEXT_PUBLIC_FRONTEND_URL // 替换为你的前端域名
    }));
    
  2. 配置RTK Query的baseQuery,开启凭证携带:

import { fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const baseQuery = fetchBaseQuery({
  baseUrl: process.env.NEXT_PUBLIC_AXIOS_BASE_DEV_URL,
  credentials: 'include', // 关键:让浏览器自动携带Cookie
});

export const authApi = createApi({
  reducerPath: 'api/auth',
  baseQuery,
  endpoints: (build) => ({
    fetchMe: build.query<OAuthResponse, void>({
      query: () => ({
        url: 'auth/me',
        method: 'GET',
      }),
    }),
  }),
});
  1. 修改后端逻辑,从请求Cookie中提取auth_token(替代之前从Authorization头读取的逻辑)。

注意:该方式要求前后端域名匹配或CORS配置正确,且后端需支持从Cookie中获取令牌。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:01:02