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

如何在Next.js中间件中获取NextAuth会话或令牌?

解决NextAuth在中间件及服务端获取会话/令牌的问题

核心问题分析

你当前的错误在于:getSession() 是 next-auth/react 包中的客户端方法,不能在中间件(服务端环境)中使用,直接传入handler也不符合API要求。下面分场景给出正确实现方式:


第一步:重构Auth配置,抽离可复用的authOptions

首先把NextAuth的配置单独抽离出来,方便在中间件、服务端组件中复用:

api/auth/[...nextauth]/route.ts

import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
import { _AUTH } from "@/app/services/shared/endpoints";

// 单独导出authOptions,供其他服务端场景使用
export const authOptions = {
    session: {
      strategy: 'jwt'
    },
    providers: [
      CredentialsProvider({
        async authorize(credentials, req){
            const res  = await fetch(_AUTH._AUTH_LOGIN, {
                method: 'POST',
                body: JSON.stringify({user:{...credentials}}),
                headers: { "Content-Type": "application/json" }
            })
            const user = await res.json()
            return user || null
        }
      })
    ],
    pages: {
      signIn: '/login',
    },
    // 建议在.env中配置NEXTAUTH_SECRET,NextAuth会自动读取,也可手动指定
    secret: process.env.NEXTAUTH_SECRET
}

export const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }

场景一:在中间件中获取会话/令牌

有两种常用方式:

方式1:使用getToken直接获取JWT令牌(推荐,适配JWT策略)

从next-auth/jwt导入getToken,传入请求对象和auth配置:

middleware.ts

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { getToken } from 'next-auth/jwt'
import { authOptions } from './app/api/auth/[...nextauth]/route'

export async function middleware(request: NextRequest) {
    // 获取JWT令牌(包含会话信息)
    const token = await getToken({ req: request, secret: authOptions.secret })
    
    // 修正逻辑:如果未登录(无token),重定向到登录页;否则允许访问
    if (!token) {
        return NextResponse.redirect(new URL('/login', request.url))
    }
    
    // 若已登录,可在这里使用token中的信息做额外校验
    console.log('当前用户令牌:', token)
    
    return NextResponse.next()
}
 
export const config = {
  matcher: [
    '/empresa/mis-empresas', // 保护该路由
  ]
}

方式2:使用NextAuth自带的withAuth中间件

更简洁的封装方式,直接用NextAuth提供的中间件工具:

middleware.ts

import { withAuth } from "next-auth/middleware"
import { NextResponse } from "next/server"

export default withAuth(
  function middleware(request) {
    // 可通过request.nextauth.token获取令牌信息
    console.log('当前用户令牌:', request.nextauth.token)
  },
  {
    callbacks: {
      authorized: ({ token }) => {
        // 验证是否登录:存在令牌则允许访问
        return !!token
      },
    },
    pages: {
      signIn: "/login", // 未登录时重定向的登录页
    },
  }
)

export const config = {
  matcher: ["/empresa/mis-empresas"],
}

场景二:在服务端组件中获取会话

使用next-auth/next/server中的getServerSession方法,传入抽离的authOptions:

示例服务端组件(app/empresa/mis-empresas/page.tsx)

import { getServerSession } from "next-auth/next/server"
import { redirect } from 'next/navigation'
import { authOptions } from "../api/auth/[...nextauth]/route"

export default async function MisEmpresasPage() {
    const session = await getServerSession(authOptions)
    
    // 若未登录,直接重定向到登录页
    if (!session) {
        redirect('/login')
    }
    
    return (
        <div>
            <h1>我的企业</h1>
            <p>当前用户信息:{JSON.stringify(session.user)}</p>
        </div>
    )
}

关键注意事项

  1. 必须配置NEXTAUTH_SECRET:可在.env文件中设置,NextAuth会自动读取,否则getToken和getServerSession会报错。
  2. 修正条件判断逻辑:原代码中session !== undefined || session !== null永远为true,因为一个值不可能同时是undefined和null,正确判断未登录应该用!session或session === null。
  3. 自定义JWT内容:如果需要在令牌中添加更多字段,可以在authOptions中添加jwt回调,比如:
// 在authOptions中添加
jwt: {
    async callback({ token, user }) {
        // 登录时将authorize返回的user字段合并到token中
        if (user) {
            token.user = user
        }
        return token
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:46:06