12. Next.js13+ Auth权限校验快速入门

2023年 9月 23日 81.7k 0

大家好这里是梦兽编程,欢迎来到next.js13+的项目实战,更多内容请查阅next.js13+项目实战专栏

无惊无危,我们已经学习了很多web服务端开发的技巧了,在我们日常开发过程中,还有一个比较重要的功能用户权限校验,一般来说做完渲染层我们经常需要做的事情就是登录。

在Next.js中配合Next-Auth使用,你将拥有一个功能非常完善的用户安全身份验证。

今天,我们将探讨如何通通过第三方API对用户进行身份认证。用户将使用他们的电子邮件和咪咪登录生成JWT,JWT存放在Cookie中,这意味着它回与所有的请求一起发送。

Next Auth中我们我们可以作用在中间件,服务端组件还有客户端组件中灵活切换使用。

点击链接加入群聊梦兽编程交流区交流更多技术golang,node.js,vue,java,react

大致的关系如图所示:

在本文中我们回使用Next Auth制作一个简单的登录注册。当然如果你不想自己设置Auth数据库,可以直接使用内置的第三方API功能,比如Google,Github,FusionAuth...等。

快速入门

npm install next-auth --save

安装成功后,我们需要在根目录中的env文件添加NEXTAUTH_SECRET关键词密钥,密钥内容任君选中。

因为next-auth是以route api的方式进行工作的,所以我们还需在api文件夹下添加/app/api/auth/[…nextauth]/route.ts这样的目录+route.ts文件,这是强制要求。

在这个文件中我们需要定义一个providers,这个providers可以有很多,如果你使用Github可以直接加入GithubProviders方法即可,我们这里使用的是自定义的方式需要用到CredentialsProvider

import { authenticate } from "@/services/authService"
import NextAuth from "next-auth"
import type { AuthOptions } from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"

export const authOptions: AuthOptions = {
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      credentials: {
        email: { label: "Email", type: "text" },
        password: { label: "Password", type: "password" }
      },
      async authorize (credentials, req) {
        if (typeof credentials !== "undefined") {
		  // 认证邮件和密码是否正确
          const res = await authenticate(credentials.email, credentials.password)
          if (typeof res !== "undefined") {
		  	// 使用Ts的小伙伴需要自己重新声明一下User接口,要么编辑器会提示没有apiToken等其他多余的属性
            return { ...res.user, apiToken: res.token }
          } else {
            return null
          }
        } else {
          return null
        }
      }
    })
  ],
  session: { strategy: "jwt" }
}

const handler = NextAuth(authOptions)

export { handler as GET, handler as POST }

在next-auth中提供了signIn方法进行调用,当然如果你不想这么用可以直接调用/api/auth/signin

去掉我们的登录中进行代码改造

'use client'

//...
import { signIn } from 'next-auth/react'

function SignIn() {
  const handleSubmit = async (event: React.FormEvent) => {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    try {
      const payload = Object.fromEntries(data);
      const res = await signIn('credentials', {
        ...payload,
        redirect: false
      })
  };
  //...
}

export default SignIn

这样就会调用上面next-auth中的route.js的方法。

服务端组件中如何访问Next Auth当前的用户身份?

在服务端中Auth权益是存放在Session中,Next Auth给我们提供了getServerSession的方法

import { getServerSession } from "next-auth/next"
import type { NextRequest } from "next/server"
import { authOptions } from "@/app/api/auth/[...nextauth]/route"

export default async function Protected (req: NextRequest): Promise {
  // 获取user对象
  const session = await getServerSession(authOptions)

  return (
    
      
        {
          session !== null
            ? 
                Hi {session?.user.name}!
              
            : Sign in
        }
      
    
  )
}

这样,如果用户未登录,我们可以显示“登录”按钮,或者如果他们确实登录,则可以显示带有用户名的问候语。

客户端组件中的获取身份信息

在客户端中,我们使用到next-auth提供的hooks进行访问,但使用这个hooks必须先创建SessionProvider的上下文。

/app/context/client-provider.tsx
'use client'

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

export default function Provider ({
  children,
  session
}: {
  children: React.ReactNode
  session: any
}): React.ReactNode {
  return 
    {children}
  
}
// layout.tsx
import '@/app/globals.css'
import React from 'react'
import { Montserrat } from 'next/font/google'
import Provider from "@/app/context/client-provider"
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/app/api/auth/[...nextauth]/route"

const montserrat = Montserrat({ subsets: ['latin'] })

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app'
}

export default async function RootLayout ({
  children
}: {
  children: React.ReactNode
}): React.ReactNode {
  const session = await getServerSession(authOptions)

  return (
    
      
        
          {children}
        
      
    
  )
}

这样之后我们就可以在客户端的组件中使用session

'use client'

import { useSession } from "next-auth/react"
import React, { useState } from "react"

export default function ClientSideRoot (): any {
  // 用法与服务端多了一步
  const { data: session } = useSession()

  const [shown, setShown] = useState(false)
  const clickHandler = (): void => {
    setShown(!shown)
  }

  return (
    
      
        
          Hi {session?.user.name}!
        
      
      
        Protected client page
        Toggle
        {shown
          ? {JSON.stringify(session, null, 2)}
          : null
        }
      
    
  )
}

结语

看完这个文章,你已经掌握了Auth的基本用法了。更多的尝试希望你能动手试试Github的身份认证。

做完了这个身份校验后我们会发现就算我们没有登录,别的页面还是能访问。这个时候我们需要使用到中间价这个概念中间件的概念梦兽是放到下一次的章节进行讲解。

如果你现在无聊,可以进入下面的连接听梦兽Rap视频解说。

我的B站视频号更多视频动态。

微信公众号订阅[梦兽编程]

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论