# Dify 客户端 JWT 认证改造 - 前端修改总结 ## 📅 修改信息 - **修改日期**: 2025-01-XX - **版本**: v2.0 - JWT 认证版本 - **修改类型**: 架构升级 - 从直连改为代理模式 --- ## 🎯 修改目标 将 Dify AI 服务调用从 **前端直连** 改为 **通过 FastAPI 后端代理**,并使用 **JWT 认证**替代原有的 API KEY。 --- ## 📋 核心变更 ### **架构变更** ``` 旧: 前端 → Dify API (使用 API_KEY) 新: 前端 → FastAPI 后端 (使用 JWT) → Dify API (使用 API_KEY) ``` ### **认证方式变更** ``` 旧: Authorization: Bearer {DIFY_API_KEY} 新: Authorization: Bearer {frontendJWT} ``` ### **API 端点变更** ``` 旧: https://api.dify.ai/v1/chat-messages 新: http://172.16.0.55:8000/dify/chat-messages ``` --- ## 📁 修改的文件清单 ### **1. 核心服务层** (1 个文件) - ✅ `app/services/dify-client.server.ts` - Dify 客户端核心 **主要修改**: - 导入 `API_BASE_URL` 从配置文件 - `DIFY_CONFIG.API_URL` 改为 `${API_BASE_URL}/dify` - `difyFetch` 函数添加 `jwt` 参数 - 所有 client 方法添加 `jwt?` 参数 - 添加 401 错误处理(JWT 认证失败) ### **2. API 路由层** (6 个文件) 所有路由都添加了 JWT 获取、验证和传递逻辑: - ✅ `app/routes/api.chat-messages.tsx` - 聊天消息发送 - ✅ `app/routes/api.parameters.tsx` - 应用参数获取 - ✅ `app/routes/api.conversations.tsx` - 会话列表获取 - ✅ `app/routes/api.messages.tsx` - 会话消息历史 - ✅ `app/routes/api.conversations.$id.tsx` - 会话删除 - ✅ `app/routes/api.conversations.$id.name.tsx` - 会话重命名 **统一修改模式**: ```typescript // 1. 获取 JWT const { getUserSession } = await import("~/api/login/auth.server"); const { frontendJWT } = await getUserSession(request); // 2. JWT 验证 if (!frontendJWT) { return json({ error: 'JWT认证失败,请重新登录' }, { status: 401 }); } // 3. 传递给 difyClient await difyClient.method(..., frontendJWT); // 4. 错误处理 const status = error.message?.includes('JWT认证失败') ? 401 : 500; ``` --- ## 🔐 配置迁移说明 ### **前端配置(已废弃)** ```bash # .env - 这些配置不再使用 NEXT_PUBLIC_APP_ID=http://nas.7bm.co:12980/app/46539478-3281-4e98-a445-6da9dc078e95/configuration NEXT_PUBLIC_APP_KEY=app-N3su9tKyMMnqxt2EMgOkVof7 ``` ### **后端配置(需要添加)** **这些配置应该移到 FastAPI 后端**: ```python # FastAPI 环境变量配置 DIFY_API_URL = "http://nas.7bm.co:12980/v1" DIFY_API_KEY = "app-N3su9tKyMMnqxt2EMgOkVof7" DIFY_APP_ID = "46539478-3281-4e98-a445-6da9dc078e95" ``` ### **前端新配置** ```bash # .env - 前端只需要配置 FastAPI 地址 API_BASE_URL=http://172.16.0.55:8000 ``` --- ## 🛣️ 后端需要实现的路由 | 路由 | 方法 | 说明 | |------|------|------| | `/dify/parameters` | GET | 获取应用参数 | | `/dify/conversations` | GET | 获取会话列表 | | `/dify/messages` | GET | 获取会话消息历史 | | `/dify/chat-messages` | POST | 发送聊天消息(支持流式) | | `/dify/conversations/{id}/name` | POST | 重命名会话 | | `/dify/conversations/{id}` | DELETE | 删除会话 | | `/dify/messages/{id}/feedbacks` | POST | 消息反馈 | **详细对接文档**: `docs/dify-proxy-backend-integration.md` --- ## ⚠️ 关键注意事项 ### **1. JWT 认证必须实现** - 所有请求都携带 `Authorization: Bearer {JWT}` - JWT 验证失败必须返回 **401 状态码** - 错误格式:`{"error": "JWT认证失败,请重新登录"}` ### **2. 流式响应必须支持** - `/dify/chat-messages` 接口支持流式响应(SSE) - 响应头:`Content-Type: text/event-stream` - 不能缓冲,必须实时转发 ### **3. 配置安全** - `DIFY_API_KEY` 只能存在后端 - 前端代码中不再包含任何 Dify 凭据 - 所有敏感配置通过环境变量管理 ### **4. 错误处理** - JWT 不存在: **401** - JWT 过期/无效: **401** - 其他错误: **500** --- ## 🧪 测试清单 ### **前端测试** - [ ] 聊天消息发送(流式) - [ ] 聊天消息发送(非流式) - [ ] 会话列表加载 - [ ] 会话切换和消息历史 - [ ] 会话重命名 - [ ] 会话删除 - [ ] JWT 过期后跳转登录 ### **后端测试** - [ ] JWT 验证逻辑 - [ ] 所有 API 路由返回正确 - [ ] 流式响应正常工作 - [ ] 错误返回正确状态码 - [ ] 日志记录完整 --- ## 📊 代码统计 - **修改文件数**: 7 个 - **新增代码行数**: ~150 行 - **修改代码行数**: ~200 行 - **核心逻辑变更**: 认证方式 + API 端点 --- ## 🚀 部署步骤 ### **1. 后端准备** ```bash # 1. 在 FastAPI 中实现 /dify/* 路由 # 2. 配置 Dify API 凭据 # 3. 集成 JWT 验证逻辑 # 4. 测试所有接口 ``` ### **2. 前端部署** ```bash # 1. 确认后端已就绪 npm run build npm run start ``` ### **3. 联调测试** ```bash # 1. 测试聊天功能 # 2. 测试会话管理 # 3. 测试 JWT 过期处理 # 4. 检查日志输出 ``` --- ## 📝 代码示例 ### **前端调用示例** ```typescript // app/routes/api.chat-messages.tsx const { getUserSession } = await import("~/api/login/auth.server"); const { frontendJWT } = await getUserSession(request); const response = await difyClient.createChatMessage( inputs, query, user, responseMode, conversationId, files, frontendJWT // 传递 JWT ); ``` ### **后端实现示例** ```python # FastAPI 路由 @app.post("/dify/chat-messages") async def create_chat_message( request: Request, authorization: str = Header(None) ): # 1. 验证 JWT jwt_token = authorization.replace("Bearer ", "") user_info = verify_jwt(jwt_token) if not user_info: raise HTTPException(status_code=401, detail="JWT认证失败") # 2. 调用 Dify API headers = {"Authorization": f"Bearer {DIFY_API_KEY}"} body = await request.json() # 3. 转发流式响应 if body.get("response_mode") == "streaming": return StreamingResponse(...) ``` --- ## 📞 支持与文档 ### **详细文档** - **后端对接文档**: `docs/dify-proxy-backend-integration.md` - **JWT 实现文档**: `docs/JWT_IMPLEMENTATION.md` - **CLAUDE.md**: 项目总体架构说明 ### **相关链接** - [Dify 官方文档](https://docs.dify.ai/) - [FastAPI 文档](https://fastapi.tiangolo.com/) - [JWT 规范](https://jwt.io/) --- ## ✅ 检查清单 ### **前端(已完成)** - [x] dify-client.server.ts 修改 - [x] 所有 API 路由添加 JWT - [x] 错误处理完善 - [x] 日志输出优化 - [x] 配置迁移说明 ### **后端(待实现)** - [ ] /dify/* 路由实现 - [ ] JWT 验证集成 - [ ] 流式响应支持 - [ ] 错误处理规范 - [ ] 日志记录完善 - [ ] CORS 配置(如需) ### **联调测试(待完成)** - [ ] 基础功能测试 - [ ] JWT 认证测试 - [ ] 流式响应测试 - [ ] 错误处理测试 - [ ] 性能测试 --- ## 🎉 总结 本次修改完成了 Dify 服务调用的架构升级: - ✅ **安全性提升**: API KEY 不再暴露在前端 - ✅ **统一认证**: 使用项目统一的 JWT 认证体系 - ✅ **便于管理**: 所有 Dify 配置集中在后端 - ✅ **向后兼容**: 保留了原有的 API 接口设计 **下一步**: 等待后端实现完成后进行联调测试。 --- **修改完成日期**: 2025-01-XX **文档版本**: v1.0