204 lines
5.0 KiB
Markdown
204 lines
5.0 KiB
Markdown
# 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) |