本文实现用户验证。
设置Next Auth
安装:npm i next-auth@4.23.1
在/app/api下新建auth/[…nextauth]目录,再新建route.tsx文件。
// /app/api/auth/[...nextauth]/route.tsx
import NextAuth from "next-auth";
const handler = NextAuth({
providers: [],
});
export { handler as GET, handler as POST };
再在 .env添加NEXTAUTH_URL和NEXTAUTH_SECRET,其中NEXTAUTH_SECRET由openssl生成:openssl rand -base64 32
// .env
...
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="ngGYFDDXYGNA2dwG+9IVC+klO+0OYxGlViovNGc4aBk="
提交Git,命名:Set up NextAuth。
配置Github提供者
访问:https://github.com/settings/apps,添加一个OAuth应用,获取Client ID和Client Secrets。并在 .env里配置进去。
// .env
...
GITHUB_ID="aaf751407814c4719fbd"
GITHUB_SECRET="091a5f24badf9513bb7525cb72ce17972200e09e"
再在app/api/auth/[…nextauth]/route.tsx添加Github提供者信息。
提交Git,命名:Configure Github Provider。
添加 Prisma 适配器
这个在《掌握Next.js》系列中已讲过,主要步骤参考官网。
https://authjs.dev/reference/adapter/prisma
- 安装prisma-adapter:npm i @auth/prisma-adapter
- 创建四个model: Account,Session,User,VerificationToken
- 迁移:npx prisma migrate dev
完成后,访问 /api/auth/signin,用github账户登录,成功后返回首页,同时检查数据库的User、Account表已有记录。
提交Git,命名:Add the Prisma adapter。
添加登录和注销链接
需要用到useSession的Hook, 需要添加SessionProvider, 《掌握Next.js》里已有细讲,这里只给出结果。
添加目录 /app/auth/, 添加Provider.tsx
// app/auth/Provider.tsx
"use client";
import { SessionProvider } from "next-auth/react";
import { PropsWithChildren } from "react";
const AuthProvider = ({ children }: PropsWithChildren) => {
return <SessionProvider>{children}</SessionProvider>;
};
export default AuthProvider;
再到layout.tsx用AuthProvider将所有子组件包起来。
再到NavBar添加登录注销链接。
查看网页。
提交Git,命名:Add the Login and Logout links。
更改导航栏的布局
我们把账户的登录状态显示在NavBar的右侧。调整NavBar的样式。将左侧与右侧的账户登录信息用Flex包起来,使用 justify=’between’,再在外面包一层Container,免得屏幕很宽时太靠近左右侧。
查看页面。
提交Git,命名:Change the layout of the navbar。
添加下拉菜单
Radix-UI的DropdownMenu很容易使用。
网页效果。
提交Git,命名:Add a drop-down menu to show the current user。
故障排除:头像未加载
从Google等提供者获取信息时,可能会遇到头像不显示的情况,可以尝试以下方法。
- 添加Avatar属性 referrerPolicy=”no-referrer”
2.修改next.config.js,添加HTTP头相关信息。
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers(){
return [
{
source: '/:path*',
headers: [
{key:'referrer-policy', value:'no-referrer'}
]
}
]
}
}
module.exports = nextConfig
提交Git,命名:Fix avatar not loading.
重构导航栏
NavBar布局和每个布局块均放在一起,不太符合单一责任原则,需要重构。有两种选择,一种像之前一样将细节分离到另外文件,另一种则是将子组件放在当前文件里。这两种选择没有对错,本次就放在当前文件里实现。
另外为保持AuthStatus和NavLinks样式一致,抽了一个样式形成 nav-link,设置在global.css中。
// app/global.css
......
@layer utilities {
.nav-link {
@apply text-zinc-500 hover:text-zinc-800 transition-colors
}
}
提交Git,命名:Refactor the nav bar.
添加加载Skeleton
给AuthStatus组件添加Skeleton,否则会有闪烁看上去比较奇怪。
提交Git,命名:Add a loading skeleton.
保护应用程序
创建、删除、编辑等操作是需要保护的,未验证的用户不能操作。利用next-auth自带的middleware就可做到。
在项目的根目录(不是app目录下),创建middleware.ts文件,注意拼写不能错,这是约定的。设置 /issues/new 和 /issues/:id+/edit 必须要登录才能操作。:id+ 表示参数1个至多个,《掌握Next.js》系列已有介绍,这里不赘述。在未登录状态下,测试访问新建和编辑页面,均会弹出窗口要求用户验证。
// middleware.ts
export {default} from 'next-auth/middleware';
export const config = {
matcher:[
'/issues/new',
'/issues/:id+/edit'
]
}
删除如何保护?它是没有具体URL的。
我们应该在IssueDetailPage就判断是否登录,如果没登录,就不显示按钮。这就用到服务器session的获取,这在《掌握Next.js》系列里也介绍过。
提取出authOptions, 形成文件 /app/auth/authOptions.ts.
// /app/auth/authOptions.ts
import prisma from "@/prisma/client"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { AuthOptions } from "next-auth";
import GitHubProvider from "next-auth/providers/github";
const authOptions:AuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
GitHubProvider({
clientId: process.env.GITHUB_ID!,
clientSecret: process.env.GITHUB_SECRET!,
}),
],
session: {
strategy: "jwt",
},
};
export default authOptions;
在app/issues/[id]/page.tsx里判断session,不存在就不显示编辑和删除按钮。
相应API端点也进行session的判断。
提交Git,命名:Secure the application.
小结
本文实现了用户验证功能。
下一篇实现分配问题到用户的功能。