第 8 章:认证与授权(Authentication & Authorization)
8.1 认证 vs 授权
- 认证(Authentication) :确认用户身份,比如是否已登录。
- 授权(Authorization) :确认用户是否有权限执行某些操作,比如是否是管理员。
8.2 认证方式概览
认证方式 | 优点 | 缺点 |
---|---|---|
Cookie Session | 简单易用 | 需手动处理加密、过期等 |
JWT Token | 前后端分离友好 | 容易被盗用,需安全存储 |
NextAuth.js | 快速集成多平台登录 | 定制化复杂 |
8.3 Cookie Session 登录示例(原生实现)
📄 pages/api/login.js
js
export default function handler(req, res) {
const { username, password } = req.body;
if (username === 'admin' && password === '123456') {
res.setHeader('Set-Cookie', 'token=admin-token; Path=/; HttpOnly');
res.status(200).json({ success: true });
} else {
res.status(401).json({ success: false, error: 'Invalid credentials' });
}
}
📄 pages/api/logout.js
js
export default function handler(req, res) {
res.setHeader('Set-Cookie', 'token=; Path=/; Max-Age=0');
res.status(200).json({ success: true });
}
📄 页面中获取 cookie(服务端)
js
// pages/dashboard.js
export async function getServerSideProps({ req }) {
const token = req.cookies.token;
if (token !== 'admin-token') {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
return { props: {} };
}
8.4 JWT 登录认证(推荐 API 模式)
📦 安装依赖:
bash
npm install jsonwebtoken
📄 lib/jwt.js
js
import jwt from 'jsonwebtoken';
const SECRET = 'your-secret-key';
export const signToken = (payload) =>
jwt.sign(payload, SECRET, { expiresIn: '1h' });
export const verifyToken = (token) =>
jwt.verify(token, SECRET);
📄 pages/api/login.js
js
import { signToken } from '../../lib/jwt';
export default function handler(req, res) {
const { username, password } = req.body;
if (username === 'admin' && password === '123456') {
const token = signToken({ username });
res.setHeader('Set-Cookie', `token=${token}; Path=/; HttpOnly`);
res.status(200).json({ success: true });
} else {
res.status(401).json({ error: 'Invalid credentials' });
}
}
📄 验证 Token 示例
js
import { verifyToken } from '../../lib/jwt';
export async function getServerSideProps({ req }) {
const { token } = req.cookies;
try {
const user = verifyToken(token);
return { props: { user } };
} catch (e) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
}
8.5 使用 NextAuth.js 快速集成认证(推荐方式)
📦 安装:
bash
npm install next-auth
📄 pages/api/auth/[...nextauth].js
js
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
export default NextAuth({
providers: [
CredentialsProvider({
name: 'Credentials',
credentials: {
username: { label: '用户名', type: 'text' },
password: { label: '密码', type: 'password' },
},
async authorize(credentials) {
const { username, password } = credentials;
if (username === 'admin' && password === '123456') {
return { id: 1, name: 'admin' };
}
return null;
},
}),
],
pages: {
signIn: '/login',
},
session: {
strategy: 'jwt',
},
});
📄 页面中获取会话:
js
import { useSession, signOut } from 'next-auth/react';
export default function Dashboard() {
const { data: session } = useSession();
if (!session) return <p>未登录</p>;
return (
<div>
<p>欢迎,{session.user.name}</p>
<button onClick={() => signOut()}>退出</button>
</div>
);
}
📄 SSR 中获取会话:
js
import { getSession } from 'next-auth/react';
export async function getServerSideProps(context) {
const session = await getSession(context);
if (!session) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
return { props: { session } };
}
8.6 保护页面与接口
场景 | 推荐方式 |
---|---|
页面访问保护 | 使用 getServerSideProps 检查 cookie/JWT/session |
接口保护 | 在 API 路由中验证 cookie 或 token |
中间件权限拦截 | 在 middleware.js 中基于 cookie 重定向 |
客户端使用 | useSession() 或全局状态管理 |
✅ 小结
认证方式 | 推荐场景 | 特点 |
---|---|---|
Cookie Session | SSR 项目 / 简单登录系统 | 快速简单,适合小项目 |
JWT Token | 前后端分离、多端兼容 | 灵活易扩展,可搭配移动端 |
NextAuth.js | 快速上线,支持社交登录 | 内置 Google/GitHub 等 OAuth,功能完善 |