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

使用Next-Auth Credentials:默认页面下登录/登出后如何重定向?

解决方案

1. 首页登录按钮跳转至内置Credentials登录页

直接通过链接跳转至NextAuth内置的Credentials登录页面,并携带登录成功后的回调URL,避免调用signIn()时因缺少凭据触发错误:

// pages/index.tsx
import Link from 'next/link';

export default function Home() {
  return (
    <div>
      <Link href="/api/auth/signin/credentials?callbackUrl=/dashboard/beers">
        <button>登录</button>
      </Link>
    </div>
  );
}

如果偏好使用signIn()函数(NextAuth v4+支持),确保调用时仅指定provider和callbackUrl,不传递凭据参数,此时会自动跳转到登录表单:

// pages/index.tsx
import { signIn } from 'next-auth/react';

export default function Home() {
  return (
    <div>
      <button onClick={() => signIn('credentials', { callbackUrl: '/dashboard/beers' })}>
        登录
      </button>
    </div>
  );
}

2. 登录成功跳转指定URL

通过上述方法传递callbackUrl参数后,登录成功时NextAuth会自动跳转到该地址。如果需要统一所有Credentials登录的跳转目标,可在signIn回调中处理:

// [...nextauth].ts
callbacks: {
  async signIn({ user, account }) {
    // 仅对Credentials登录生效
    if (account?.provider === 'credentials' && user) {
      return '/dashboard/beers';
    }
    return true;
  },
  // ...其他回调
}

3. 登出后重定向至登录页

在调用signOut()时指定回调URL,或者通过redirect回调统一处理登出请求:

方法一:客户端调用时指定

// 任意页面的登出按钮
import { signOut } from 'next-auth/react';

<button onClick={() => signOut({ callbackUrl: '/api/auth/signin' })}>登出</button>

方法二:全局配置(推荐)

在[...nextauth].ts的redirect回调中判断请求类型,自动处理登出跳转:

// [...nextauth].ts
callbacks: {
  async redirect({ url, baseUrl, params }) {
    // 处理登出请求,重定向到登录页
    if (params?.action === 'signout') {
      return `${baseUrl}/api/auth/signin`;
    }
    // 登录成功时,若没有指定callbackUrl则跳转到默认目标
    if (url === baseUrl) {
      return `${baseUrl}/dashboard/beers`;
    }
    return url;
  },
  // ...其他回调
}

4. 优化authorize函数健壮性

修改authorize函数,先判断凭据是否存在,避免空凭据触发不必要的错误:

// [...nextauth].ts - CredentialsProvider的authorize方法
async authorize(credentials, req) {
  // 缺少邮箱或密码时直接返回null
  if (!credentials?.email || !credentials?.password) {
    return null;
  }

  const collection = await getDbCollection("users");
  const { email, password } = credentials;
  
  try {
    const user = await collection.findOne({ email, pwd: password }) as UserData;

    if (!user) {
      throw new Error("Invalid Login");
    }

    return {
      id: user._id as string,
      name: user.name,
      email: user.email,
      role: user.role,
      domain: user.domain
    };
  } catch (error) {
    throw new Error("Invalid Login");
  }
}

内容的提问来源于stack exchange,提问作者m3.b

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 11:55:01