Files

204 lines
5.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# JWT 认证系统实现说明
## 概述
本项目实现了一个基于JWT的前端认证系统,配合OAuth2.0统一认证使用。该系统在用户通过OAuth2.0认证后,生成一个前端专用的JWT Token,包含用户信息和权限数据。
## 核心功能
### 1. JWT生成与管理 (`app/utils/jwt.ts`)
- 生成包含用户信息的JWT
- 验证JWT的有效性
- 检查JWT过期状态
- 解析JWT获取用户信息
### 2. 认证服务集成 (`app/api/login/auth.server.ts`)
- 在OAuth2.0登录成功后自动生成JWT
- 在Token刷新时重新生成JWT
- JWT自动存储在session中
### 3. 前端认证Hook (`app/hooks/useAuth.ts`)
- 提供便捷的认证状态获取
- JWT验证和过期检查
- 用户权限检查功能
## 使用方法
### 在Loader中返回认证信息
```typescript
// app/routes/your-route.tsx
export async function loader({ request }: LoaderFunctionArgs) {
const { getUserSession } = await import("~/api/login/auth.server");
const sessionData = await getUserSession(request);
return Response.json({
// 你的其他数据
yourData: "...",
// 认证信息
isAuthenticated: sessionData.isAuthenticated,
userInfo: sessionData.userInfo,
userRole: sessionData.userRole,
frontendJWT: sessionData.frontendJWT
});
}
```
### 在组件中使用认证信息
```typescript
// 在你的React组件中
import { useAuth } from '~/hooks/useAuth';
export default function YourComponent() {
const auth = useAuth();
// 检查认证状态
if (!auth.isAuthenticated) {
return <div></div>;
}
// 使用用户信息
return (
<div>
<h1>{auth.nickName}</h1>
<p>ID: {auth.userId}</p>
<p>: {auth.userRole}</p>
{/* 权限检查 */}
{auth.isAdmin() && (
<button></button>
)}
{auth.hasRole('developer') && (
<button></button>
)}
</div>
);
}
```
### JWT验证和状态检查
```typescript
const auth = useAuth();
// 验证JWT
const jwtValidation = auth.validateJWT();
if (!jwtValidation.valid) {
console.error('JWT无效:', jwtValidation.error);
}
// 检查是否即将过期
if (auth.isJWTExpiringSoon()) {
console.log('JWT即将过期,建议刷新页面');
}
// 获取过期时间
const expiration = auth.getJWTExpiration();
if (expiration) {
console.log('JWT过期时间:', new Date(expiration * 1000));
}
```
## JWT载荷结构
```typescript
{
// 标准字段
sub: string; // 用户唯一标识(来自IDaaS)
iss: string; // 发行者: 'docreview-system'
aud: string; // 受众: 'docreview-frontend'
iat: number; // 签发时间
exp: number; // 过期时间
// 自定义用户信息字段
user_id: string; // 数据库中的用户ID
username: string; // 用户名
nick_name: string; // 用户昵称
email?: string; // 邮箱
phone_number?: string; // 手机号
ou_id: string; // 组织单位ID
ou_name: string; // 组织单位名称
is_leader: boolean; // 是否为负责人
user_role: string; // 用户角色
}
```
## 安全特性
1. **过期时间控制**: JWT过期时间设置为OAuth Token过期时间的90%,确保JWT在OAuth Token之前过期
2. **自动刷新**: 当OAuth Token刷新时,自动重新生成JWT
3. **签名验证**: 使用HS256算法和固定密钥进行签名验证
4. **过期检查**: 提供5分钟缓冲时间的过期预警
## 调试工具
使用 `AuthDebugInfo` 组件在开发阶段查看JWT状态:
```typescript
import { AuthDebugInfo } from '~/components/auth/AuthDebugInfo';
export default function DebugPage() {
return (
<div>
<h1></h1>
<AuthDebugInfo />
</div>
);
}
```
## 配置说明
### JWT密钥配置
`app/utils/jwt.ts` 中修改JWT密钥:
```typescript
// 生产环境中应该从环境变量读取
const JWT_SECRET = 'your-super-secret-jwt-key-change-this-in-production-2024';
```
### JWT配置参数
```typescript
const JWT_CONFIG = {
algorithm: 'HS256',
issuer: 'docreview-system',
audience: 'docreview-frontend'
};
```
## 注意事项
1. **生产环境安全**:
- JWT密钥应该从环境变量读取
- 删除或隐藏 `AuthDebugInfo` 组件
- 考虑使用更强的签名算法
2. **性能优化**:
- JWT验证在前端进行,减少服务器压力
- 使用session存储避免频繁重新生成
3. **错误处理**:
- JWT验证失败时应该引导用户重新登录
- 过期检查应该在关键操作前进行
## 工作流程
1. 用户通过OAuth2.0登录
2. `callback.tsx` 接收认证结果并保存用户信息到数据库
3. 根据保存的用户信息生成JWT
4. JWT存储在session中
5. 后续请求通过 `getUserSession` 检查JWT状态
6. 前端通过 `useAuth` hook 使用认证信息
7. 当OAuth Token刷新时,自动重新生成JWT
## 扩展功能
可以考虑的扩展功能:
- JWT黑名单机制
- 多设备登录管理
- 权限细粒度控制
- JWT刷新接口
- 客户端JWT存储(LocalStorage/SessionStorage