182 lines
5.2 KiB
Markdown
182 lines
5.2 KiB
Markdown
# 认证模块 (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 文件重新导出认证函数
|
||
|
||
```typescript
|
||
// ✅ 正确的导入方式
|
||
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 错误处理
|
||
|
||
## 🚀 使用指南
|
||
|
||
### 在路由中检查用户认证
|
||
|
||
```typescript
|
||
// 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 });
|
||
}
|
||
```
|
||
|
||
### 处理用户登出
|
||
|
||
```typescript
|
||
// 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;
|
||
}
|
||
```
|
||
|
||
### 创建登录会话
|
||
|
||
```typescript
|
||
// 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 安全配置
|
||
```typescript
|
||
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 登录流程
|
||
|
||
```mermaid
|
||
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 数据
|
||
|
||
## 📖 相关文档
|
||
|
||
- [OAuth2.0认证协议集成指南](./OAuth2.0认证协议集成指南.md)
|
||
- [Remix Session Storage 文档](https://remix.run/docs/en/main/utils/sessions)
|
||
- [Cookie Security Best Practices](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) |