Files
leaudit-platform-frontend/app/api/login/README.md
T

5.2 KiB
Raw Blame History

认证模块 (Authentication Module)

这个文件夹包含了整个应用的用户认证和会话管理功能。

📁 文件结构

app/api/login/
├── README.md                    # 本文档
├── auth.server.ts              # 🔐 认证核心实现
├── auth-exports.server.ts      # 📤 认证函数导出入口
├── oauth-client.ts             # 🌐 OAuth2.0 客户端
├── token-manager.server.ts     # 🎫 Token 管理器
└── OAuth2.0认证协议集成指南.md # 📖 OAuth2.0 集成文档

🔧 核心文件说明

auth.server.ts - 认证核心实现

包含所有认证相关的核心功能:

  • 会话管理: 基于 Cookie 的安全会话存储
  • 用户认证: 检查用户登录状态
  • Token 刷新: 自动刷新过期的 OAuth Token
  • 登录/登出: 创建和销毁用户会话

主要函数:

  • getUserSession() - 获取用户会话(带 Token 刷新)
  • createUserSession() - 创建登录会话
  • logout() - 销毁会话并登出
  • getSession() - 获取原始会话对象

auth-exports.server.ts - 导出入口

这个文件解决了 Remix + Vite 架构中的一个重要问题:

问题: 同构文件(.tsx)不能直接导入 .server.ts 文件 原因: 防止服务器端敏感代码被打包到客户端 解决: 通过这个 .server.ts 文件重新导出认证函数

// ✅ 正确的导入方式
import { getUserSession } from "~/api/login/auth-exports.server";

// ❌ 错误的导入方式(会导致构建错误)
import { getUserSession } from "~/api/login/auth.server";

oauth-client.ts - OAuth2.0 客户端

实现 OAuth2.0 认证协议的客户端功能:

  • 生成授权 URL
  • 获取访问令牌
  • 获取用户信息
  • 状态值生成和验证

token-manager.server.ts - Token 管理

负责 OAuth Token 的生命周期管理:

  • Token 有效期检查
  • 自动刷新即将过期的 Token
  • Token 错误处理

🚀 使用指南

在路由中检查用户认证

// app/routes/some-route.tsx
import { getUserSession } from "~/api/login/auth-exports.server";

export async function loader({ request }: LoaderFunctionArgs) {
  const { isAuthenticated, userRole } = await getUserSession(request);
  
  if (!isAuthenticated) {
    return redirect("/login");
  }
  
  // 检查权限
  if (userRole !== 'developer') {
    throw new Response("权限不足", { status: 403 });
  }
  
  return json({ userRole });
}

处理用户登出

// app/routes/some-route.tsx
import { logout } from "~/api/login/auth-exports.server";

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  
  if (formData.get("intent") === "logout") {
    return logout(request);
  }
  
  return null;
}

创建登录会话

// app/routes/callback.tsx
import { createUserSession } from "~/api/login/auth-exports.server";

export async function loader({ request }: LoaderFunctionArgs) {
  // OAuth 认证成功后...
  
  // 根据用户信息判断角色
  const userRole = userInfo.username === "admin" ? "developer" : "common";
  
  return createUserSession(true, userRole, "/dashboard");
}

🛡️ 安全特性

cookie: {
  httpOnly: true,    // 防止 XSS 攻击
  sameSite: "lax",   // CSRF 保护
  secure: false,     // 开发环境设为 false,生产环境应为 true
  maxAge: 7200,      // 2小时过期
}

Token 自动刷新

  • 检查 Token 是否即将过期(5分钟内)
  • 自动使用 refresh_token 获取新的 access_token
  • 刷新失败时自动登出用户

用户角色权限

  • common: 普通用户,基本功能访问权限
  • developer: 开发者/管理员,完整系统管理权限

🔄 OAuth2.0 登录流程

sequenceDiagram
    participant User as 用户
    participant App as 应用
    participant IDaaS as IDaaS平台
    
    User->>App: 访问受保护页面
    App->>User: 重定向到 /login
    User->>App: 点击"统一身份认证登录"
    App->>IDaaS: 重定向到 IDaaS 登录页
    User->>IDaaS: 完成登录
    IDaaS->>App: 回调并返回 code
    App->>IDaaS: 使用 code 获取 access_token
    IDaaS->>App: 返回 access_token
    App->>IDaaS: 使用 access_token 获取用户信息
    IDaaS->>App: 返回用户信息
    App->>App: 创建用户会话
    App->>User: 重定向到目标页面

🚨 注意事项

开发环境配置

  1. 确保 OAuth 配置正确(app/config/api-config.ts
  2. IDaaS 平台中配置正确的回调地址
  3. 检查 Cookie 的 secure 设置(开发环境为 false

生产环境部署

  1. 使用环境变量管理敏感信息(secrets)
  2. 启用 HTTPS 并设置 secure: true
  3. 配置正确的域名和回调地址
  4. 监控 Token 刷新日志

调试技巧

  • 查看浏览器 Application 标签页中的 Cookies
  • 检查服务器控制台的认证相关日志
  • 使用 Remix Dev Tools 查看 loader 数据

📖 相关文档