在现代 Web 开发中,认证(Authentication) 与 授权(Authorization) 是构建安全应用的核心环节。Next.js 14 引入的 App Router 架构结合 React Server Components 与 Server Actions,为开发者提供了更安全、更高效的认证实现方式。
本文将带你从零搭建一个具备完整认证与授权能力的 Next.js 应用系统。
一、核心概念区分
在动手前,先厘清三个关键概念:
| 概念 | 说明 |
|---|---|
| 认证(Authentication) | 验证“你是谁”——例如通过用户名/密码、OAuth 登录等方式确认用户身份。 |
| 会话管理(Session Management) | 在用户登录后,持续跟踪其身份状态,通常通过 Cookie 或 Token 实现。 |
| 授权(Authorization) | 决定“你能做什么”——例如普通用户只能查看自己的资料,管理员可删除内容。 |
二、整体架构设计
Next.js 推荐采用 服务端优先 的安全模型:
- 表单提交 → Server Action(服务端执行)
- 会话存储 → HttpOnly Cookie + JWT(或数据库)
- 权限控制 → Middleware(乐观检查) + Data Access Layer(安全检查)
⚠️ 安全原则:所有敏感操作必须在服务端验证身份与权限,客户端仅用于 UI 展示。
三、Step 1:实现用户注册与登录(认证)
1. 创建注册表单(Client Component)
// app/signup/page.tsx
'use client'
import { signup } from '@/app/actions/auth'
import { useActionState } from 'react'
export default function SignupForm() {
const [state, action, pending] = useActionState(signup, undefined)
return (
<form action={action}>
<div>
<label htmlFor="name">Name</label>
<input name="name" />
</div>
{state?.errors?.name && <p>{state.errors.name[0]}</p>}
<div>
<label htmlFor="email">Email</label>
<input name="email" type="email" />
</div>
{state?.errors?.email && <p>{state.errors.email[0]}</p>}
<div>
<label htmlFor="password">Password</label>
<input name="password" type="password" />
</div>
{state?.errors?.password && (
<ul>
{state.errors.password.map(err => <li key={err}>- {err}</li>)}
</ul>
)}
<button type="submit" disabled={pending}>
Sign Up
</button>
</form>
)
}
2. 定义表单验证(Zod Schema)
// lib/definitions.ts
import {
z } from 'zod'
export const SignupFormSchema = z.object({
name: z.string().min(2).trim(),
email: z.string().email().trim(),
password: z.string()
.min(8)
.regex(/[a-zA-Z]/)
.regex(/[0-9]/)
.regex(/[^a-zA-Z0-9]/)
})
export type FormState = {
errors?: {
name?: string[]
email?: string[]
password?: string[]
}
message?: string
}
3. 实现 Server Action(服务端逻辑)
// app/actions/auth.ts
'use server'
import {
SignupFormSchema, FormState } from '@/lib/definitions'
import {
db } from '@/lib/db'
import {
users } from '@/lib/schema'
import bcrypt from 'bcrypt'
import {
createSession } from '@/lib/session'
import {
redirect } from 'next/navigation'
export

最低0.47元/天 解锁文章
1998

被折叠的 条评论
为什么被折叠?



