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

如何基于NextAuth实现多登录页并调用指定API路由

解决NextAuth多登录页+动态API路由的方案

核心思路是通过自定义登录标识区分登录场景,在NextAuth配置中动态切换API调用,并通过会话控制跳转路由,具体实现步骤如下:

1. 独立登录页面配置

为owner和user分别创建登录页面,调用signIn时传递自定义标识和目标跳转地址:

商家登录页(pages/owner/login.jsx)

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

export default function OwnerLogin() {
  return (
    <form onSubmit={(e) => {
      e.preventDefault()
      const { email, password } = e.target
      signIn("credentials", {
        email: email.value,
        password: password.value,
        callbackUrl: "/owner/dashboard",
        loginType: "owner" // 自定义标识,标记商家登录
      })
    }}>
      <input type="email" name="email" placeholder="商家邮箱" required />
      <input type="password" name="password" placeholder="密码" required />
      <button type="submit">商家登录</button>
    </form>
  )
}

用户登录页(pages/user/login.jsx)

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

export default function UserLogin() {
  return (
    <form onSubmit={(e) => {
      e.preventDefault()
      const { email, password } = e.target
      signIn("credentials", {
        email: email.value,
        password: password.value,
        callbackUrl: "/user/profile",
        loginType: "user" // 自定义标识,标记普通用户登录
      })
    }}>
      <input type="email" name="email" placeholder="用户邮箱" required />
      <input type="password" name="password" placeholder="密码" required />
      <button type="submit">用户登录</button>
    </form>
  )
}

2. NextAuth核心配置动态处理API路由

在pages/api/auth/[...nextauth].js中,通过CredentialsProvider的authorize方法根据loginType动态调用对应API,并通过JWT存储登录标识用于后续跳转:

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

export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      // 声明接收自定义参数loginType
      credentials: {
        email: { label: "邮箱", type: "email" },
        password: { label: "密码", type: "password" },
        loginType: { label: "登录类型", type: "hidden" }
      },
      async authorize(credentials) {
        const { email, password, loginType } = credentials
        // 根据登录类型切换API地址
        const apiRoute = loginType === "owner" ? "/api/owner" : "/api/user"
        
        // 调用对应角色的认证API
        const res = await fetch(`${process.env.NEXTAUTH_URL}${apiRoute}`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ email, password })
        })

        const user = await res.json()
        // 认证成功则返回用户信息+登录类型
        if (res.ok && user) return { ...user, loginType }
        return null
      }
    })
  ],
  session: { strategy: "jwt" }, // 用JWT存储会话信息
  jwt: {
    // 将loginType写入JWT
    async encode({ secret, token }) {
      if (token?.loginType) token.loginType = token.loginType
      return jwt.sign(token, secret)
    },
    async decode({ secret, token }) {
      return jwt.verify(token, secret)
    }
  },
  callbacks: {
    // 控制登录后的跳转逻辑
    async redirect({ url, baseUrl }) {
      const session = await getSession()
      // 根据会话中的loginType跳转对应页面
      if (session?.user?.loginType === "owner") {
        return `${baseUrl}/owner/dashboard`
      } else if (session?.user?.loginType === "user") {
        return `${baseUrl}/user/profile`
      }
      // 兜底返回默认地址
      return url.startsWith(baseUrl) ? url : baseUrl
    }
  }
})

3. 实现角色专属认证API

分别创建商家和用户的认证API,处理各自的账号校验逻辑:

商家认证API(pages/api/owner.js)

export default async function handler(req, res) {
  if (req.method !== "POST") return res.status(405).json({ msg: "仅支持POST请求" })
  
  const { email, password } = req.body
  // 此处替换为商家账号校验逻辑(比如查询数据库)
  const validOwner = await checkOwnerCredentials(email, password)
  
  if (validOwner) {
    res.status(200).json({ id: validOwner.id, email: validOwner.email, role: "owner" })
  } else {
    res.status(401).json({ msg: "商家账号或密码错误" })
  }
}

用户认证API(pages/api/user.js)

export default async function handler(req, res) {
  if (req.method !== "POST") return res.status(405).json({ msg: "仅支持POST请求" })
  
  const { email, password } = req.body
  // 此处替换为普通用户账号校验逻辑
  const validUser = await checkUserCredentials(email, password)
  
  if (validUser) {
    res.status(200).json({ id: validUser.id, email: validUser.email, role: "user" })
  } else {
    res.status(401).json({ msg: "用户账号或密码错误" })
  }
}

关键说明

  • 自定义loginType参数是核心,用于在NextAuth流程中区分不同登录场景
  • 使用JWT会话策略可以持久化登录类型,确保跳转逻辑准确
  • 若需复用登录表单,可以封装通用组件,通过props传递loginType和callbackUrl

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:53:06