切换语言
切换主题

NextAuth.js 入门教程:Credentials 登录配置与会话管理完全指南

引言

打开 NextAuth.js 官方文档那天,我盯着屏幕上密密麻麻的配置项发了半个小时呆。Provider、Session、Adapter、JWT、Callbacks…每个词都认识,串起来就不知道在说啥。最让人抓狂的是,文档说”默认用JWT”,但下一段又说”用数据库时自动切换Session”——那我到底该用哪个?

说实话,我当时真的有点想放弃,直接去用Clerk算了。但转念一想,Clerk虽然快,每个月10,000活跃用户的免费额度用完就得掏钱,而且很多定制化的东西改不了。NextAuth.js虽然上手难点,但完全免费、完全掌控。

这篇文章不会给你罗列所有配置项(那太折磨人了),而是聚焦最常用的Credentials登录场景——用户名密码登录、会话管理、数据库集成,这几个最核心的问题搞明白了,NextAuth.js就不难了。

理解 NextAuth.js 的核心概念

NextAuth.js 到底在做什么?

用一句话说: NextAuth.js 是个”认证中间件”,帮你管理”谁登录了”和”登录状态如何存储”。它不管你用什么数据库、不管你的UI长啥样,只负责验证用户身份和记住登录状态。

和Clerk、Supabase Auth的区别?简单说:

  • Clerk: 给你漂亮的登录UI、用户管理界面,30分钟搞定,但要花钱(超过10,000月活跃用户)
  • Supabase Auth: 如果你用Supabase数据库,认证功能基本白送,集成特别丝滑
  • NextAuth.js: 完全免费开源,但登录界面、用户注册、数据库逻辑都得自己写

2025年的趋势挺有意思——NextAuth.js虽然还是很多人在用,但Clerk这种”开箱即用”的方案正在快速抢市场。我理解,毕竟花几天写认证代码,不如把时间用在核心功能上。不过如果你是个人项目或者想完全掌控,NextAuth.js还是值得学的。

三个必须理解的概念

1. Provider(提供者): 用户怎么登录?

就是登录方式。NextAuth.js 支持50多种,最常见的:

  • OAuth提供者: Google、GitHub、Facebook…点一下就登录,你不用管密码
  • Credentials提供者: 用户名+密码,最传统的方式,也是本文的重点

有个坑要说: Credentials 提供者最灵活,但也最需要你自己写代码。官方甚至不推荐用它,因为安全风险全在你自己手里——密码怎么加密、怎么防暴力破解、会话怎么管理,都得自己操心。

2. Session(会话): 登录后怎么记住用户?

用户登录一次,不能每个请求都重新输密码吧? Session就是”记住登录状态”的机制。有两种方式:

  • JWT Session: 登录信息加密后塞进cookie,服务器不用存任何东西
  • Database Session: cookie里只放一个ID,真正的登录信息存数据库

这两个选哪个,是NextAuth.js最让新手懵的地方。下一节会详细讲。

3. Adapter(适配器): 用户数据存哪?

如果你想把用户信息存数据库(比如email、注册时间),就需要Adapter。NextAuth.js支持Prisma、MongoDB、MySQL各种数据库。

不过有个关键点: Credentials 提供者不会自动往数据库存用户信息。官方文档明确说了,用Credentials的话,用户账号得你自己管。NextAuth.js只负责验证登录,不负责注册和存储。

JWT vs Session: 到底该用哪个?

这是最核心的问题。我当时看了十几篇对比文章,还是拿不准主意,直到我理解了它们的本质区别。

JWT Session: 护照模式

想象你去国外旅游,护照上印着你的照片、名字、有效期。每次入境检查,海关看护照就行,不用查系统。JWT就是这样——用户登录后,服务器生成一个加密的token(就像护照),里面包含userId、email等信息,然后存到浏览器cookie里。

优点:

  • 快。不用查数据库,解密token就知道用户是谁
  • 省钱。不需要数据库来存session,特别适合serverless部署
  • 可扩展。用户量大了也不怕,因为没有session表会爆

缺点:

  • 没法强制用户下线。你发现账号被盗了,想废除某个登录? 对不起,token还没过期就废不掉(除非你维护一个黑名单,但那又需要数据库了)
  • 没法限制同时登录设备。想做”最多同时3台设备登录”? 做不到
  • token过期前无法更新信息。你在token里存了用户角色,后来角色变了? token还没过期的话,用户看到的还是旧角色

Database Session: 酒店房卡模式

酒店给你一张房卡,卡上只有房间号,你的详细信息(护照、消费记录)都在酒店系统里。每次刷卡,系统查你的房间号,确认你有权限进。Database Session也是这样——cookie里只存一个session ID,真正的用户信息存数据库。

优点:

  • 可以随时废除登录。用户点”退出所有设备”? 把数据库里的session记录删掉就行
  • 可以限制登录设备数量
  • 可以实时更新用户信息(比如权限变了,下次请求立刻生效)

缺点:

  • 慢。每个请求都要查数据库
  • 需要管理session表(创建、清理过期session)
  • 用户量大了,数据库压力会上来

决策树(重点来了)

你可能会问: 那我到底该选哪个? 我的建议:

你的应用需要"强制用户重新登录"功能吗?(比如密码被改、账号被冻结)
  ├─ 是 → 用 Database Session
  └─ 否 → 继续看下一条

你想省掉数据库,或者用serverless部署?
  ├─ 是 → 用 JWT
  └─ 否 → 继续看下一条

你的应用是个人项目/MVP,追求快速上线?
  ├─ 是 → 用 JWT(简单、省事)
  └─ 否 → 用 Database Session(企业应用更稳妥)

我自己的项目一开始用的JWT,后来加了”用户管理后台”需要踢人下线,才切换到Database Session。切换成本还挺高的,建议一开始就想清楚。

特殊情况: Credentials + Database Session

如果你用Credentials提供者,又想用Database Session,会遇到一个大坑: 官方文档说不支持

具体来说,OAuth提供者(Google、GitHub)可以无缝用Database Session,但Credentials不行。原因是NextAuth.js认为Credentials太灵活了,无法自动创建session记录。

解决办法有,但需要手动写代码,在 signIn callback里自己创建session。GitHub上有很多讨论(比如这个issue),有现成的方案可以参考。不过说实话,如果你是新手,我建议要么用JWT,要么换OAuth提供者,别给自己找麻烦。

Credentials 提供者完整配置

好,理论讲完了,现在上手写代码。我会给三个版本的示例,从简单到完整,你可以根据自己的阶段选择。

基础配置:最小可运行版本

先装依赖:

npm install next-auth

然后创建文件。注意,Next.js 13+ 用 App Router 的话,路径是 app/api/auth/[...nextauth]/route.ts;如果还在用 Pages Router,路径是 pages/api/auth/[...nextauth].js。我这里用 App Router 示范。

app/api/auth/[…nextauth]/route.ts:

import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"

const handler = NextAuth({
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      credentials: {
        email: { label: "邮箱", type: "email" },
        password: { label: "密码", type: "password" }
      },
      async authorize(credentials) {
        // 这里先hardcode一个用户,方便测试
        if (credentials?.email === "test@example.com" &&
            credentials?.password === "123456") {
          return {
            id: "1",
            name: "测试用户",
            email: "test@example.com"
          }
        }
        return null  // 登录失败
      }
    })
  ],
  session: {
    strategy: "jwt"  // 使用JWT session
  },
  pages: {
    signIn: '/login'  // 自定义登录页面(可选)
  }
})

export { handler as GET, handler as POST }

环境变量 .env.local:

NEXTAUTH_SECRET=your-super-secret-key-change-this
NEXTAUTH_URL=http://localhost:3000

关键点:

  • NEXTAUTH_SECRET: 用来加密token。生产环境必须设置,本地开发也建议设。生成方法: openssl rand -base64 32
  • authorize 函数: 验证用户身份的核心逻辑。返回用户对象表示成功,返回null表示失败

这个版本能跑起来,但用户数据是hardcode的,实际没用。下一步我们连接数据库。

关键配置项详解

在加完整示例之前,先讲几个最容易混淆的配置。

1. session.strategy: “jwt” 还是 “database”?

前面讲过,默认是 “jwt”。如果你用了 Adapter(连接数据库),会自动切换成 “database”。但如果你用 Credentials 提供者 + 想用 JWT,就得显式写 strategy: "jwt",不然可能报错。

2. callbacks: 如何在session中添加自定义字段?

默认情况下,useSession 返回的用户信息只有 nameemailimage。如果你想加 userIdrole 怎么办?

需要用 callbacks:

callbacks: {
  async jwt({ token, user }) {
    // user 只在登录时有值
    if (user) {
      token.userId = user.id  // 把userId加到token里
    }
    return token
  },
  async session({ session, token }) {
    // 把token里的userId放到session里
    session.user.userId = token.userId
    return session
  }
}

这样前端调用 const { data: session } = useSession() 时,session.user.userId 就有值了。

3. pages: 自定义登录页面

NextAuth.js 有个内置的丑陋登录页(地址是 /api/auth/signin)。如果你想用自己的登录UI,设置 pages: { signIn: '/login' }

你的登录页面需要调用:

import { signIn } from "next-auth/react"

const handleSubmit = async (e) => {
  e.preventDefault()
  const result = await signIn('credentials', {
    redirect: false,
    email,
    password
  })

  if (result?.error) {
    // 登录失败
  } else {
    // 登录成功,跳转
  }
}

完整示例:用户注册 + 登录 + 会话管理

现在来个真实可用的版本。假设你用 Prisma + PostgreSQL。

1. 先建用户表

prisma/schema.prisma:

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  password  String
  name      String?
  createdAt DateTime @default(now())
}

npx prisma migrate dev 生成表。

2. 注册接口

app/api/register/route.ts:

import { NextResponse } from "next/server"
import bcrypt from "bcryptjs"
import { prisma } from "@/lib/prisma"  // 假设你有个prisma client

export async function POST(req: Request) {
  try {
    const { email, password, name } = await req.json()

    // 检查用户是否已存在
    const existingUser = await prisma.user.findUnique({
      where: { email }
    })

    if (existingUser) {
      return NextResponse.json(
        { error: "邮箱已被注册" },
        { status: 400 }
      )
    }

    // 密码加密(重点!)
    const hashedPassword = await bcrypt.hash(password, 10)

    // 创建用户
    const user = await prisma.user.create({
      data: {
        email,
        password: hashedPassword,
        name
      }
    })

    return NextResponse.json({
      user: {
        id: user.id,
        email: user.email,
        name: user.name
      }
    })
  } catch (error) {
    return NextResponse.json(
      { error: "注册失败" },
      { status: 500 }
    )
  }
}

关键: 密码必须加密!用 bcryptargon2,别明文存数据库。

3. NextAuth配置(连接数据库)

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

import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
import bcrypt from "bcryptjs"
import { prisma } from "@/lib/prisma"

const handler = NextAuth({
  providers: [
    CredentialsProvider({
      credentials: {
        email: { label: "邮箱", type: "email" },
        password: { label: "密码", type: "password" }
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) {
          return null
        }

        // 从数据库查用户
        const user = await prisma.user.findUnique({
          where: { email: credentials.email }
        })

        if (!user) {
          return null  // 用户不存在
        }

        // 验证密码
        const isValid = await bcrypt.compare(
          credentials.password,
          user.password
        )

        if (!isValid) {
          return null  // 密码错误
        }

        // 返回用户信息(不要包含密码!)
        return {
          id: user.id,
          email: user.email,
          name: user.name
        }
      }
    })
  ],
  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60  // 30天
  },
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.userId = user.id
      }
      return token
    },
    async session({ session, token }) {
      session.user.userId = token.userId as string
      return session
    }
  },
  pages: {
    signIn: '/login'
  }
})

export { handler as GET, handler as POST }

4. 前端使用session

在服务端组件(Server Component):

import { getServerSession } from "next-auth"

export default async function ProfilePage() {
  const session = await getServerSession()

  if (!session) {
    redirect('/login')
  }

  return <div>欢迎, {session.user.name}</div>
}

在客户端组件(Client Component):

'use client'
import { useSession } from "next-auth/react"

export default function Dashboard() {
  const { data: session, status } = useSession()

  if (status === "loading") {
    return <div>加载中...</div>
  }

  if (!session) {
    return <div>请先登录</div>
  }

  return <div>你的用户ID: {session.user.userId}</div>
}

注意:

  • 服务端用 getServerSession()
  • 客户端用 useSession()
  • 客户端组件外面要包一层 <SessionProvider>(一般在layout里加)

会话管理策略与常见问题

JWT会话的正确姿势

既然选了JWT,就得用好它。几个关键点:

1. 在JWT中存储额外信息(userId、role等)

前面callbacks例子演示过了,再强调一次: jwt callback 用来往token里加东西,session callback 用来把token的东西放到session里。

实际项目中可能还需要存角色:

callbacks: {
  async jwt({ token, user }) {
    if (user) {
      token.userId = user.id
      token.role = user.role  // 假设数据库有role字段
    }
    return token
  },
  async session({ session, token }) {
    session.user.userId = token.userId as string
    session.user.role = token.role as string
    return session
  }
}

2. Token 过期时间设置

默认是30天,但你可以改:

session: {
  strategy: "jwt",
  maxAge: 7 * 24 * 60 * 60  // 7天
}

有个坑: 如果用户关闭浏览器再打开,token还在(除非手动退出登录)。如果你想”关闭浏览器就退出登录”,得在前端处理,后端JWT做不到。

3. JWT的最大限制: 无法主动废除

这是JWT最让人头疼的地方。假设你发现某个用户账号被盗了,想立刻让他下线? 对不起,做不到。Token还没过期的话,拿着token的人还是能访问。

变通方案:

  • 把token过期时间设短点(比如1小时),损失用户体验换安全
  • 维护一个token黑名单(但那又需要数据库,失去了JWT的优势)
  • 用Database Session(一劳永逸)

Database Session的实现(含Credentials提供者)

如果你一开始就选了Database Session,配置其实更简单——前提是你用OAuth提供者(Google、GitHub)。

装个Adapter:

npm install @next-auth/prisma-adapter

配置:

import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { prisma } from "@/lib/prisma"

const handler = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    })
  ]
  // strategy会自动变成"database",不用手动设
})

数据库会自动创建 UserSessionAccount 等表。

但是,如果你用Credentials提供者,就麻烦了。官方文档明确说: Credentials provider不支持database session

网上有很多解决方案,核心思路是在 signIn callback里手动创建session记录。我不建议新手这么做,太容易出错。如果一定要用Credentials + Database Session,看看这几个GitHub讨论:

或者,考虑换Clerk、Supabase Auth,他们原生支持这种组合。

最容易踩的5个坑

这几个坑我全踩过,能给你省不少时间:

1. 忘记设置 NEXTAUTH_SECRET 导致生产环境报错

本地开发时,NEXTAUTH_SECRET 可以不设(NextAuth.js会给个警告但能跑)。但部署到Vercel、Railway等平台时,如果没设这个环境变量,直接500错误。

生成方法: openssl rand -base64 32,然后加到部署平台的环境变量里。

2. Credentials 提供者默认不能用 database session

前面讲过了,再强调一次: 如果你配了Adapter,又用Credentials,会报错。要么显式设 session: { strategy: "jwt" },要么手动实现session创建逻辑。

3. useSession 在服务端组件中不可用

Next.js 13+ App Router 默认是Server Component。你在服务端组件里写 const session = useSession() 会报错,因为 hooks 只能在客户端用。

服务端要用 getServerSession():

import { getServerSession } from "next-auth"

const session = await getServerSession()

客户端要加 'use client' 指令,然后用 useSession()

4. Cookie 跨域问题

开发环境 localhost:3000,生产环境 example.com,cookie的domain不一样,导致登录状态丢失。

解决: 确保 NEXTAUTH_URL 环境变量在生产环境设置成正确的域名。不要hardcode成 localhost

5. JWEDecryptionFailed 错误

报错: JWEDecryptionFailed: decryption operation failed

原因: 你改了 NEXTAUTH_SECRET,但浏览器里还存着旧的token。旧token用新的secret解不开,就报错。

解决: 清空浏览器cookie,或者重新登录。

彩蛋: 用Middleware保护路由

如果你想让某些页面必须登录才能访问,可以用Middleware:

middleware.ts:

export { default } from "next-auth/middleware"

export const config = {
  matcher: ["/dashboard/:path*", "/profile/:path*"]
}

这样 /dashboard/profile 下的所有页面都会检查登录状态,没登录自动跳转到登录页。

实际项目建议与进阶路线

我该选哪个方案?决策建议

写了这么多,最后帮你做个决策。

场景1: 个人项目/MVP/博客

  • 推荐: NextAuth.js + JWT + Credentials
  • 理由: 完全免费,配置简单,不需要管理session表
  • 缺点: 如果后期要加”踢人下线”等功能,迁移成本高

场景2: 企业应用/SaaS产品(有预算)

  • 推荐: Clerk
  • 理由: 30分钟配置完成,UI漂亮,用户管理功能齐全,节省40-80小时开发时间
  • 缺点: 超过10,000月活跃用户要花钱,定制化受限
  • 补充: 如果你用Supabase数据库,Supabase Auth也很好(免费额度50,000 MAU)

场景3: 企业应用(无预算/需要完全掌控)

  • 推荐: NextAuth.js + Database Session + OAuth提供者(Google/GitHub)
  • 理由: 完全免费,功能完整,可以踢人下线
  • 缺点: 需要自己开发登录UI,管理数据库

场景4: 已有用户系统,只需要加认证层

  • 推荐: NextAuth.js + Credentials + JWT
  • 理由: 灵活,不侵入现有数据库结构
  • 注意: 安全措施(密码加密、防暴力破解)要自己做

我自己的选择经验: 第一个项目用了JWT,半年后需求变了要加用户管理功能,迁移到Database Session花了两天。第二个项目一开始就评估好需求,直接Database Session,省了不少事。

进阶学习路线

如果你已经跑通Credentials登录,下一步可以学:

1. OAuth 提供者(更简单,推荐优先学)

  • Google、GitHub登录比Credentials简单多了
  • 不用管密码加密、用户注册,OAuth提供商帮你搞定
  • 用户体验也更好(一键登录)

2. 中间件(Middleware): 保护路由

  • 前面演示过了,用一行代码保护整个目录
  • 比在每个页面单独检查session方便太多

3. 多角色权限管理(RBAC)

  • 在session里存 role 字段
  • 根据role显示不同内容或权限
  • 进阶可以学CASL库(细粒度权限控制)

4. 邮箱验证和密码重置

  • NextAuth.js的Email Provider(发邮件登录)
  • 自己写忘记密码功能(发重置链接)

参考资源

官方文档(必看):

实用教程:

GitHub 讨论(遇到问题时搜):

竞品对比(帮你做选择):

结论

说了这么多,其实NextAuth.js的核心就三个决策:

  1. 用什么登录方式? Credentials还是OAuth? 大部分时候OAuth(Google/GitHub)更简单
  2. 如何存储会话? JWT还是Database? 个人项目用JWT,企业应用用Database
  3. 如何验证用户? Credentials自己写验证逻辑,OAuth交给提供商

我的建议: 先跑通最小示例(本文的”最小可运行版本”),能登录了再慢慢加功能。别一上来就想把所有配置搞明白,那会劝退的。

NextAuth.js确实有学习曲线,但学会了之后你就完全掌控了认证流程。如果你想快,Clerk是好选择;如果你想省钱、学东西,NextAuth.js值得投入时间。

最后,评论区说说你遇到的问题吧。是配置哪个环节卡住了? JWT和Session还是拿不准?

推荐阅读:

  • 下一篇打算写”Next.js Middleware完全指南”,包括路由保护、A/B测试等场景

NextAuth.js Credentials 登录配置完整流程

从安装到实现用户名密码登录、会话管理的完整步骤

⏱️ 预计耗时: 2 小时

  1. 1

    步骤1: 安装和初始化 NextAuth.js

    安装依赖:
    • npm install next-auth
    • 创建 app/api/auth/[...nextauth]/route.ts

    基础配置:
    • 设置 NEXTAUTH_URL(本地:http://localhost:3000)
    • 设置 NEXTAUTH_SECRET(生成随机字符串)
    • 配置 providers 数组
  2. 2

    步骤2: 配置 Credentials Provider

    实现验证逻辑:
    1. 在 CredentialsProvider 的 authorize 函数中验证用户
    2. 从数据库查询用户(或使用硬编码测试)
    3. 验证密码(使用 bcrypt 等库)
    4. 返回用户对象(包含 id、name、email 等)

    注意:
    • authorize 函数必须返回用户对象或 null
    • 返回的对象会存储在 session 中
    • 密码验证应该在服务端进行
  3. 3

    步骤3: 选择会话策略(JWT 或 Session)

    JWT 策略(默认):
    • 适合无状态应用
    • 会话信息存储在 JWT token 中
    • 不需要数据库
    • 配置:session: { strategy: 'jwt' }

    Session 策略(需要数据库):
    • 适合需要撤销登录的应用
    • 会话信息存储在数据库中
    • 需要配置 Adapter(如 Prisma、MongoDB)
    • 配置:session: { strategy: 'database' }
  4. 4

    步骤4: 配置 Callbacks 自定义流程

    常用 Callbacks:
    • signIn:控制是否允许登录
    • jwt:自定义 JWT token 内容(JWT 策略)
    • session:自定义 session 内容

    示例:
    callbacks: {
    async jwt({ token, user }) {
    if (user) token.role = user.role
    return token
    },
    async session({ session, token }) {
    session.user.role = token.role
    return session
    }
    }
  5. 5

    步骤5: 创建登录页面和组件

    使用 NextAuth.js API:
    • signIn('credentials', { username, password }):触发登录
    • signOut():退出登录
    • useSession():获取当前会话
    • SessionProvider:包裹应用提供会话上下文

    示例:
    const { data: session } = useSession()
    if (session) {
    return <div>已登录:{session.user.name}</div>
    }
  6. 6

    步骤6: 测试和调试

    测试要点:
    • 测试正确的用户名密码能否登录
    • 测试错误的凭据是否被拒绝
    • 测试会话是否持久化
    • 测试退出登录是否清除会话

    调试方法:
    • 查看浏览器控制台错误
    • 检查服务器日志
    • 使用 NextAuth.js 调试模式
    • 检查环境变量是否正确设置

常见问题

NextAuth.js 和 Clerk、Supabase Auth 有什么区别?
NextAuth.js:
• 完全免费开源的自托管方案
• 需要自己实现登录UI和用户管理
• 但完全可控

Clerk:
• 提供完整的UI和管理界面
• 但超过10,000月活跃用户需要付费

Supabase Auth:
• 适合使用Supabase数据库的项目
• 集成简单但绑定数据库
JWT 和 Session 应该选哪个?
JWT适合无状态应用、个人项目,不需要数据库,但无法撤销单个会话。Session适合企业应用、需要撤销登录的场景,需要配置数据库Adapter,但可以精确控制会话。
Credentials 登录安全吗?
安全,但需要注意:
1) 密码必须加密存储(使用bcrypt等库)
2) 验证逻辑必须在服务端进行
3) 使用HTTPS传输
4) 实现密码强度要求
5) 考虑添加验证码防止暴力破解
如何自定义登录页面?
在NextAuth配置中使用pages选项:pages: { signIn: '/auth/login' }。

然后创建自定义登录页面,使用signIn('credentials', { username, password })触发登录。

也可以完全自定义UI,只使用NextAuth.js的API。
如何获取当前登录用户?
在客户端使用useSession() hook:
const { data: session } = useSession()

在服务端使用getServerSession():
const session = await getServerSession(authOptions)

session对象包含user信息(id、name、email等)。
如何实现角色和权限控制?
在callbacks中自定义JWT或Session内容,添加role字段。然后在页面或API路由中检查session.user.role,根据角色决定是否允许访问。也可以使用Middleware进行全局权限检查。
NextAuth.js 支持哪些数据库?
NextAuth.js通过Adapter支持多种数据库:Prisma(PostgreSQL、MySQL、SQLite等)、MongoDB、TypeORM、Drizzle ORM等。使用Adapter后会自动切换为Session策略,会话信息存储在数据库中。
  • 如果你对用户权限管理感兴趣,可以看我之前写的”RBAC权限设计实践”

15 分钟阅读 · 发布于: 2025年12月19日 · 修改于: 2026年1月22日

评论

使用 GitHub 账号登录后即可评论

相关文章