Skip to content

Next.js 鉴权

Next Auth 简介

bash
pnpm add next-auth
ts
import type { NextAuthOptions } from 'next-auth'

import { userService } from '@/services/user'
import CredentialsProvider from 'next-auth/providers/credentials'
import process from 'node:process'

export const authOptions: NextAuthOptions = {
  pages: {
    error: '/error',
    newUser: '/login',
    signIn: '/login',
    signOut: '/signout',
    verifyRequest: '/auth/verify-request',
  },
  providers: [
    CredentialsProvider({
      async authorize(credentials, _) {
        try {
          return await userService.login(credentials)
        }
        catch (error) {
          console.error(error)
          return null
        }
      },
      credentials: {
        password: { label: 'Password', type: 'password' },
        username: { label: 'Username', type: 'text' },
      },
      name: 'Credentials',
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
}

新建 app/api/auth/[...nextauth]/route.ts 文件,内容如下:

ts
import { authOptions } from '@/lib/auth'
import NextAuth from 'next-auth'

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

通过 signIn() 方法登录:

tsx

通过 signOut() 方法退出登录:

退出登录组件示例:

tsx
import { signOut } from 'next-auth/react'

export default function SignOutButton() {
  return (
    <button onClick={() => signOut()}>Sign Out</button>
  )
}

退出登录会重新加载页面,可以通过传入 callbackUrl 参数来指定退出登录后跳转的页面,通过 redirect 参数来指定退出登录后是否重定向。

后端鉴权

通过 Session 可以确定用户是否登录:

ts
import { getServerSession } from 'next-auth'

export async function GET(request: NextRequest) {
  const session = await getServerSession({ req: request })
  if (!session) {
    return new Response('Unauthorized', { status: 401 })
  }
}

获取 JWT Token:

ts
import { getToken } from 'next-auth/jwt'

export async function GET(request: NextRequest) {
  const token = await getToken({ req: request })
  // token?.sub 为用户 ID
}