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登录成功

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

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

相关推荐
donecoding3 分钟前
pnpm 配好了,为什么执行的还是另一份?命令入口与运行时排查
node.js·前端工程化
江屿风6 分钟前
【Plain Language Large Model】【从浏览器到全栈:一课精通Node.js三剑客】流食般投喂
笔记·前端框架·npm·node.js·js·npx
liuchangng3 小时前
React 19 + Vite 6 实战:从教材 PDF 到 866 词间隔重复单词 App
前端·react.js·pdf·vite·开源项目
SomeOtherTime4 小时前
node.js基础(AI回答)
node.js
鸿蒙开发16 小时前
Three.js 首帧卡顿排查:compileAsync 之后,为什么还会停一下?
react.js·three.js
雨季mo浅忆1 天前
记录Node.js安全漏洞及其内置Brotli解码器问题
node.js·安全性测试
tommyjiatong1 天前
资安底座连环雷:从 PHP2Shell 到 Node2Shell
node.js·php
小李科技1 天前
【性能优化】事件委托:目标定位与 React/Vue 实战
前端·vue.js·react.js·面试·性能优化·前端框架
csj501 天前
前端基础之《React(16)—Modal组件封装》
前端·react.js
SEO_juper1 天前
Bash 交叉验证 robots.txt 和 sitemap:两个文件自相矛盾,页面永远收录不了
开发语言·python·node.js·json·bash