Next15 + Prisma + Auth5 实战讲解

依赖包安装

Next 安装

bash 复制代码
npx create-next-app@latest

根据需要选择配置

js 复制代码
1 What is your project named? my-app
2 Would you like to use TypeScript? No / Yes
3 Would you like to use ESLint? No / Yes
4 Would you like to use Tailwind CSS? No / Yes
5 Would you like your code inside a `src/` directory? No / Yes
6 Would you like to use App Router? (recommended) No / Yes
7 Would you like to use Turbopack for `next dev`?  No / Yes
8 Would you like to customize the import alias (`@/*` by default)? No / Yes
9 What import alias would you like configured? @/*

Prisma 安装

  • 项目使用版本为6.2.1
bash 复制代码
yarn add prisma@6.2.1 @prisma/client@6.2.1
  • 初始化
bash 复制代码
npx prisma init
npx prisma generate
  • 其他开发依赖
bash 复制代码
yarn add kysely

Auth 安装

  • install
bash 复制代码
yarn add next-auth@beta
  • auth secret 生成
  1. OpenSSL 命令行生成
bash 复制代码
openssl rand -base64 32  
  1. auth CLI
bash 复制代码
npx auth secret

Auth配置

  1. 例如Github登录, 就要先创建 GITHUB_ID 和 GITHUB_SECRET
  2. 在 .env.development 文件中放入环境变量
js 复制代码
NEXTAUTH_SECRET = 上面生成的 auth-secret
GOOGLE_CLIENT_ID = ****
GOOGLE_CLIENT_SECRET = ****
NEXTAUTH_URL = http://localhost:3000
GITHUB_ID = ****
GITHUB_SECRET = ****

根目录创建auth.ts, 并写入, 以下是完整auth代码

ts 复制代码
import NextAuth from 'next-auth'
import CredentialsProvider from "next-auth/providers/credentials";
import { findUser } from "libs/server_utils"
import Google from "next-auth/providers/google";
import GitHub from "next-auth/providers/github";

export const { handlers, signIn, signOut, auth } = NextAuth({
  secret: process.env.NEXTAUTH_SECRET,
  debug: true, // 启用调试模式
  logger: {
    error(error: unknown) {
      console.error("Auth Error:", error);
    },
  },
  providers: [
    // google登录
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    // github登录
    GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    CredentialsProvider({
      name: 'Credentials',
      // 定义用户名和密码参数
      credentials: {
        username: { label: "Username" },
        password: { label: "Password", type: "password" },
      },
      authorize: async (credentials) => {
        if (!credentials || !credentials.username || !credentials.password) {
          return null;
        }
        // 检查用户是否存在, 结合prisma数据库操作
        const user = await findUser({
          username: credentials.username as string,
          password: credentials.password as string
        })
        if (!user || user.code == 500) {
          return null;
        }
        return user;
      }
    })
  ],
  session: { strategy: "jwt" },
  pages: {
    signIn: '/login'
  },
  callbacks: {
    async authorized({ request, auth }) {
      const url = request.nextUrl
      const user = auth?.user;
      if (url.pathname.startsWith('/admin') && !user) {
        return false
      }
      return true
    },
    jwt: async ({ token, user }) => {
      if ((user as { username?: string })?.username) {
        token.username = (user as { username: string }).username;
      }
      return token
    },
    session({ session, token }) {
      console.log("session=", session)
      console.log("token=", token)
      session.user = {
        id: token.sub as string,
        name: token.username as string || token.name,
        email: token.email as string,
        image: token.picture,
        emailVerified: null,
      };
      return session;
    },
  }
})

用户密码登录(Credentials)

  • 登录页面
  • 部分代码示例
ts 复制代码
import { signIn } from "next-auth/react";
const submitFormData = async (e: FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  const result = await signIn("credentials", {
    username: formData.username,
    password: formData.password,
    redirect: false,
  });
  if (result?.error) {
    toast.warning(result.error)
    return;
  }
  if (result?.ok) {
    redirect("/")
  }
}
  • 登录成功

Google登录

  • GOOGLE_CLIENT_ID 创建

创建GoogleAuth应用

  • 创建完成后,写入环境变量即可
  • 示例代码
ts 复制代码
const handleLogin = async () => {
    try {
      const res = await signIn("google");
    } catch (error) {
      console.error("登录失败:", error);
    }
  };

GitHub登录

  • GITHUB_ID 创建

创建 GitHub OAuth 应用

  • 创建完成后,写入环境变量即可

  • 示例代码

ts 复制代码
<Button variant="outline" className="w-full cursor-pointer" onClick={() => signIn("github", { callbackUrl: "/home" })}>
  <GitHubLogoIcon />
  <span className="sr-only">Login with GitHub</span>
</Button>

Auth登录成功

如果想对开发细节进一步了解, 请访问 仓库链接

如果对你有帮助, 请点赞鼓励下

相关推荐
G等你下课2 小时前
你还在 import { Button } from './components'?
前端·react.js
挽淚2 小时前
AI对话+React 项目实战(半成品)
javascript·react.js
PineappleCoder2 小时前
React函数组件的"生活管家"——useEffect Hook详解
前端·react.js
G等你下课2 小时前
React 中的 Diff 算法:理解虚拟 DOM 的高效更新机制
前端·react.js
PineappleCoder2 小时前
当 useContext 牵手 useReducer,我悟了前端状态管理的「丝滑密码」
前端·react.js
十盒半价2 小时前
React 面试必问:JSX 中 map 的 key 为什么不能随便写?一文吃透原理与最佳实践
前端·react.js·trae
WildBlue2 小时前
React 路由守卫:前端安全与控制的魔法钥匙 🗝️
前端·react.js·前端框架
OEC小胖胖2 小时前
渲染篇(一):从零实现一个“微型React”:Virtual DOM的真面目
前端·react.js·前端框架·web
德育处主任Pro2 小时前
『React』条件渲染的7种方法
前端·react.js·前端框架
lichenyang45315 小时前
Axios封装以及添加拦截器
前端·javascript·react.js·typescript