第 8 章:认证与授权(Authentication & Authorization)

第 8 章:认证与授权(Authentication & Authorization)


8.1 认证 vs 授权

  • 认证(Authentication) :确认用户身份,比如是否已登录。
  • 授权(Authorization) :确认用户是否有权限执行某些操作,比如是否是管理员。

8.2 认证方式概览

认证方式 优点 缺点
Cookie Session 简单易用 需手动处理加密、过期等
JWT Token 前后端分离友好 容易被盗用,需安全存储
NextAuth.js 快速集成多平台登录 定制化复杂

📄 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,功能完善
相关推荐
moyu846 分钟前
Pinia 状态管理:现代 Vue 应用的优雅解决方案
前端
Deepsleep.8 分钟前
吉比特(雷霆游戏)前端二面问题总结
前端·游戏
wycode18 分钟前
# 面试复盘(2)--某硬件大厂前端
前端·面试
怪可爱的地球人19 分钟前
ts枚举(enum)
前端
做你的猫22 分钟前
深入剖析:基于Vue 3与Three.js的3D知识图谱实现与优化
前端·javascript·vue.js
渊不语26 分钟前
富文本编辑器自定义图片等工具栏-完整开发文档
前端
用户239712822487027 分钟前
taro+vue3+vite项目 tailwind 踩坑记,附修复后的模板源码地址
前端
做你的猫31 分钟前
深入剖析:基于Vue 3的高性能AI聊天组件设计与实现
前端·javascript·vue.js
G佳伟33 分钟前
vue拖动排序,vue使用 HTML5 的draggable拖放 API实现内容拖并排序,并更新数组数据
前端·vue.js·html5
Bling_Bling_138 分钟前
ES6新语法特性(第二篇)
开发语言·前端·es6