第 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,功能完善
相关推荐
云枫晖11 分钟前
手写Promise-构造函数
前端·javascript
文心快码BaiduComate12 分钟前
用Comate Zulu开发一款微信小程序
前端·后端·微信小程序
王王碎冰冰15 分钟前
基于 Vue3@3.5+跟Ant Design of Vue 的二次封装的 Form跟搜索Table
前端·vue.js
naice1 小时前
我对github的图片很不爽了,于是用AI写了一个图片预览插件
前端·javascript·git
天蓝色的鱼鱼1 小时前
Element UI 2.X 主题定制完整指南:解决官方工具失效的实战方案
前端·vue.js
RoyLin1 小时前
TypeScript设计模式:门面模式
前端·后端·typescript
小奋斗1 小时前
千量数据级别的数据统计分析渲染
前端·javascript
小文刀6962 小时前
CSS-响应式布局
前端
三小河2 小时前
overflow:auto 滚动的问题,以及flex 布局中如何设置
前端·javascript
薛定谔的算法2 小时前
phoneGPT:构建专业领域的检索增强型智能问答系统
前端·数据库·后端