首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Next-Auth 配置记录

Next-Auth 配置记录

原创
作者头像
tonglei0429
发布2025-10-29 20:27:44
发布2025-10-29 20:27:44
1180
举报

Next-Auth 笔记

1. 添加依赖:

代码语言:bash
复制
npm install next-auth@beta

2. 创建 /app/auth.ts

代码语言:typescript
复制
import NextAuth, { DefaultSession, User } from "next-auth";
import Credentials from "next-auth/providers/credentials";

declare module "next-auth" {
    /**
     * 登录成功后, Session 中会包含用户 id、mob_icc、mob_num 信息,正常情况下,
     * 前端只需要使用 id 就可以了,其他信息可以从数据库中查询
     */
    interface Session {
        user: {
            id: string,
            mob_icc: string,
            mob_num: string,
        } & DefaultSession["user"]
    }

    /**
     * 登录成功后, User 中会包含用户 id、mob_icc、mob_num 信息,正常情况下,
     * 前端只需要使用 id 就可以了,其他信息可以从数据库中查询
     */
    interface User {
        id: string,
        mob_icc: string,
        mob_num: string,
    }
}

export const { handlers, signIn, signOut, auth } = NextAuth({
    basePath: process.env.NEXT_PUBLIC_BASE_PATH + "/api/auth", // 自定义 auth 路由,如果项目不是根目录,需要配置
    trustHost: true,
    useSecureCookies: false,
    providers: [
        Credentials({ 
            // Credentials 认证方式,当没有第三方登录时使用
            credentials: {
                mob_icc: {}, // 自定义认证项,可以是用户名密码,也可以是手机号验证码等等
                mob_num: {},
                checkcode: {},
            },
            authorize: async (credentials) => { // 自定义认证逻辑
                let user: User | null = null;
                const mob_icc = credentials?.mob_icc;
                const mob_num = credentials?.mob_num;
                const checkcode = credentials?.checkcode;

                // 验证过程略

                // 登录成功时,返回 User
                user = {
                    id: "1", // 实际项目中,这里应该是数据库中的用户 ID
                    mob_icc,
                    mob_num,
                };
                return user;

                // 登录失败时,返回 null
                return null;
            },
        }),
    ],
    callbacks: {
        jwt({ token, user }) {
            // 登录成功时,将用户信息添加到 token 中,只存 id 就够
            if (user) { // User is available during sign-in
                token.id = user.id;
                token.mob_icc = user.mob_icc;
                token.mob_num = user.mob_num;
            }
            return token;
        },
        session({ session, token }) {
            // 登录成功时,将 token 中的用户信息添加到 session 中, 其实只取 id 就够
            return {
                ...session,
                user: {
                    ...session.user,
                    id: token.id as string,
                    mob_icc: token.mob_icc as string,
                    mob_num: token.mob_num as string,
                },
            }
        },
    },
})

3. 创建 /app/api/auth/...nextauth/route.ts

代码语言:typescript
复制
/**
 * 登录路由,使用 Credentials 认证方式
 * 登录成功后,会返回一个包含用户信息的 Session
 * 登录失败时,会返回 null
 * 这段基本不用变
 */
import { handlers } from "@/auth";
export const { GET, POST } = handlers;

4. 登录页面

服务端认证比较容易,只需要调用 signIn 方法即可,认证成功后,会返回一个包含用户信息的 Session,认证失败时,会返回 null。

但是服务端不擅长处理登录状态,所以需要在客户端处理登录状态。

在客户端认证时,如果认证是部署在根目录,一般按官方文档的方式处理,就是在登录成功后,将用户信息添加到 Session 中,然后在客户端使用 useSession 钩子获取用户信息。

但是如果认证不是部署在根目录,比如部署在 /app 目录下,用官方的配置方法无法成功,即使配置 basePath 也无效。

这时候可以新建一个 action.ts 文件,声明其在只服务端运行,然后包裹一下 signIn 方法,这样就能可以解决客户端认证失败的问题了,例如:

代码语言:typescript
复制
"use server";
import { signIn } from "@/app/auth";

export const loginAction = async (formData: FormData) => {
    const mob_icc = formData.get("mob_icc");
    const mob_num = formData.get("mob_num");
    const checkcode = formData.get("checkcode");

    const result = await signIn("credentials", {
        basePath: process.env.NEXT_PUBLIC_BASE_PATH,
        mob_icc,
        mob_num,
        checkcode,
    });

    return result;
}

5. 获取Session

如果需要在客户端获取 Session,就在 layout.tsx 文件中添加 SessionProvider 组件,例如:

代码语言:tsx
复制
import { SessionProvider } from "next-auth/react";
import { auth } from "@/app/auth";

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  // 获取服务器会话
  const session = await auth();

  return (
    <html lang="en">
      <body>
        <SessionProvider session={session}>
          {children}
        </SessionProvider>
      </body>
    </html>
  );
}

这样客户端页面只需要调用 useSession 钩子即可获取用户信息,例如:

代码语言:tsx
复制
import { useSession } from "next-auth/react";

const { data: session } = useSession();

在客户端调用的好处是,不需要在服务端处理登录状态,只需要在客户端获取用户信息,就可以知道用户是否登录了。

如果只在服务端获取 Session,就需要在服务端调用 auth 方法,例如:

代码语言:typescript
复制
const session = await auth();

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Next-Auth 笔记
    • 1. 添加依赖:
    • 2. 创建 /app/auth.ts
    • 3. 创建 /app/api/auth/...nextauth/route.ts
    • 4. 登录页面
    • 5. 获取Session
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档