【Next.js 项目实战系列】06-身份验证

news/2024/10/23 11:44:07/

原文链接

CSDN 的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话,给我的库点个star,关注一下吧 

上一篇【Next.js 项目实战系列】05-删除 Issue

身份验证

配置 Next-Auth​

本节代码链接

具体内容可参考Authentication

Refactor NavBar​

本节代码链接

# /app/Navbar.tsx"use client";
import { Avatar, Box, DropdownMenu, Flex, Text } from "@radix-ui/themes";
import classNames from "classnames";
import { useSession } from "next-auth/react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { AiFillBug } from "react-icons/ai";
import { Skeleton } from "@/app/components";const NavBar = () => {return (<nav className="border-b mb-5 px-5 py-5"><Flex align="center" justify="between"><NavLinks /><Avator /></Flex></nav>);
};export default NavBar;const links = [{ label: <AiFillBug />, href: "/" },{ label: "DashBoard", href: "/dashboard" },{ label: "Issues", href: "/issues" },
];const NavLinks = () => {const currentPath = usePathname();return (<ul className="flex gap-6 items-center">{links.map((link) => (<li key={link.href}><LinkclassName={classNames({"text-zinc-900": link.href === currentPath,"text-zinc-500": link.href !== currentPath,"hover:text-zinc-800 transaition-colors": true,})}href={link.href}>{link.label}</Link></li>))}</ul>);
};const Avator = () => {const { status, data: session } = useSession();if (status === "loading") return <Skeleton width="3rem" />;if (status === "unauthenticated")return (<LinkclassName="text-zinc-500 hover:text-zinc-800 transaition-colors"href="/api/auth/signin">Sign In</Link>);return (<Box><DropdownMenu.Root><DropdownMenu.Trigger><Avatarsrc={session!.user!.image!}fallback="?"size="2"radius="full"className="cursor-pointer"referrerPolicy="no-referrer"/></DropdownMenu.Trigger><DropdownMenu.Content><DropdownMenu.Label><Text size="2">{session!.user!.email}</Text></DropdownMenu.Label><DropdownMenu.Item><Link href="/api/auth/signout">Sign Out</Link></DropdownMenu.Item></DropdownMenu.Content></DropdownMenu.Root></Box>);
};

Secure the Application​

本节代码链接

AuthOptions​

首先,我们应该将 AuthOptions 放到一个单独的文件里备用

# /app/api/auth/AuthOptions.tsximport prisma from "@/prisma/client";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { NextAuthOptions } from "next-auth";
import Github from "next-auth/providers/github";const authOptions: NextAuthOptions = {adapter: PrismaAdapter(prisma),providers: [Github({clientId: process.env.GITHUB_CLIENT_ID!,clientSecret: process.env.GITHUB_CLIENT_SECRET!,}),],
};export default authOptions;

保护 API 与 页面​

在除 GET 外的所有 API 中都应该加上确认是否有 session 的验证

# /app/api/issues/[id]/route.tsx...
+ import { getServerSession } from "next-auth";
+ import authOptions from "@/app/api/auth/AuthOptions";export async function PATCH(request: NextRequest,{ params }: { params: { id: string } }) {
+   const session = await getServerSession(authOptions);
+   if (!session) return NextResponse.json({}, { status: 401 });...}export async function DELETE(request: NextRequest,{ params }: { params: { id: string } }) {
+   const session = await getServerSession(authOptions);
+   if (!session) return NextResponse.json({}, { status: 401 })...}

同样,我们应该在一些页面将删除修改的组件隐藏

# /app/issues/[id]/page.tsx+ import { getServerSession } from "next-auth";
+ import authOptions from "@/app/api/auth/AuthOptions";interface Props {params: { id: string };}const IssueDeatilPage = async ({ params }: Props) => {
+   const session = await getServerSession(authOptions);const issue = await prisma.issue.findUnique({where: { id: parseInt(params.id) },});if (!issue) notFound();return (<Grid columns={{ initial: "1", sm: "5" }} gap="5"><Box className="md:col-span-4"><IssueDetails issue={issue} /></Box>
+       {session && (<Box><Flex direction="column" gap="3"><EditIssueButton issueId={issue.id} /><DeleteIssueButton issueId={issue.id} /></Flex></Box>)}</Grid>);};export default IssueDeatilPage;

MiddleWare​

同样我们可以使用 MiddleWare 来保护路由

export { default } from "next-auth/middleware";export const config = {matcher: ["/issues/new", "/issues/edit/:id+"],
};

CSDN 的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话,给我的库点个star,关注一下吧 

 下一篇讲分配 Issue 给用户

下一篇【Next.js 项目实战系列】07-分配 Issue 给用户


http://www.ppmy.cn/news/1541320.html

相关文章

怎么把flv格式转换成mp4?将flv格式换成MP4格式的简单方法

怎么把flv格式转换成mp4&#xff1f;flv这一昔日网络视频领域的璀璨明星&#xff0c;凭借其小巧的文件体积与卓越的流媒体传输性能&#xff0c;曾在网络视频时代初期大放异彩&#xff0c;成为无数网络视频爱好者的首选。然而&#xff0c;随着科技的日新月异与多媒体设备的多元化…

SpringBoot实现的智能个人理财平台

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理个人理财系统的相关信息成为必然。开发合适…

GEE传奇服务端中自定义颜色文字发送脚本教程

功能说明: 发送自定义颜色的文字信息.格式: GuildNoticeMsg 255 233 发送自定义颜色的文字信息. Self 参数一是前景颜色,参数二是背景颜色,参数三是要发送的文字信息,参数四等于Self时只发送给自己, 等于Group时发送给组队, 等于National时发送给自己国家的人(使用于国战), 等于…

FreeRTOS源码概述(内存管理,入口函数,数据类型和编程规范)创建任务(声光色影,使用任务参数)删除任务(使用遥控器控制音乐)

FreeRTOS源码概述 入口函数 在 Core\Src\main.c 的 main 函数里&#xff0c;初始化了 FreeRTOS 环境、创建了任务&#xff0c;然后启动 调度器。源码如下&#xff1a; /* Init scheduler */osKernelInitialize(); /* Call init function for freertos objects (in freertos.c…

CSS基本语法

CSS 如何学习 CSS是什么CSS怎么用&#xff08;快速入门&#xff09;CSS选择器&#xff08;重点 难点&#xff09;美化网页&#xff08;文字、阴影、超链接、列表、渐变...&#xff09;盒子模型浮动定位网页动画&#xff08;特效&#xff09; CSS概述 Cascading Style Sheet…

从零开始实现 C++ 双向链表:深入理解链表底层原理

文章目录 前言&#xff1a;1. 主要数据结构2. 迭代器的实现3. 链表的实现3.1 基本结构3.2 链表的插入与删除3.3 其他成员函数 4. 迭代器操作与遍历链表5. 拷贝构造与赋值运算符6. 总结 前言&#xff1a; 在 C 标准库中&#xff0c;std::list 是一种非常常用的数据结构&#xff…

QT模块--GUI和QtWidgets

一、GUI QtGui 模块是 Qt 的一个核心模块&#xff0c;它提供了与图形用户界面相关的低级功能。尽管它的名字中包含 “GUI”&#xff0c;但它实际上并不直接提供具体的窗口小部件&#xff08;widgets&#xff09;。相反&#xff0c;QtGui 提供了底层的支持&#xff0c;这些支持…

高级SQL技巧掌握

高级SQL技巧掌握 在数据驱动的时代&#xff0c;掌握SQL不仅仅是为了解决具体问题&#xff0c;它更像是一把钥匙&#xff0c;帮助你打开数据分析的大门。你准备好提升你的SQL技能了吗&#xff1f;在这篇文章中&#xff0c;我们将一起探索十个必备的高级SQL查询技巧&#xff0c;…