配置优化:切换到生产环境内网地址并添加Dify前端修改文档
1. 更新API配置:梅州端口51703切换到内网地址172.16.0.55:8073 2. 测试环境切换到正确的端口8873 3. 启动脚本改用生产模式:start:pm2:production:multi 4. 添加紧急修改文档:URGENT-前端必须修改.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+11
-13
@@ -72,12 +72,12 @@ const portConfigs: Record<string, Partial<ApiConfig>> = {
|
||||
// 主要
|
||||
// 梅州
|
||||
'51703': {
|
||||
// baseUrl: 'http://172.16.0.55:8073',
|
||||
// documentUrl: 'http://172.16.0.55:8073/docauditai/',
|
||||
// uploadUrl: 'http://172.16.0.55:8073/admin/documents'
|
||||
baseUrl: 'http://nas.7bm.co:8073',
|
||||
documentUrl: 'http://nas.7bm.co:8073/docauditai/',
|
||||
uploadUrl: 'http://nas.7bm.co:8073/admin/documents'
|
||||
baseUrl: 'http://172.16.0.55:8073',
|
||||
documentUrl: 'http://172.16.0.55:8073/docauditai/',
|
||||
uploadUrl: 'http://172.16.0.55:8073/admin/documents'
|
||||
// baseUrl: 'http://nas.7bm.co:8873',
|
||||
// documentUrl: 'http://nas.7bm.co:8873/docauditai/',
|
||||
// uploadUrl: 'http://nas.7bm.co:8873/admin/documents'
|
||||
},
|
||||
|
||||
|
||||
@@ -136,14 +136,11 @@ const configs: Record<string, ApiConfig> = {
|
||||
|
||||
// 测试环境
|
||||
testing: {
|
||||
// baseUrl: 'http://172.16.0.55:8873',
|
||||
// documentUrl: 'http://172.16.0.55:8873/docauditai/',
|
||||
// uploadUrl: 'http://172.16.0.55:8873/admin/documents',
|
||||
baseUrl: 'http://nas.7bm.co:8073',
|
||||
documentUrl: 'http://nas.7bm.co:8073/docauditai/',
|
||||
uploadUrl: 'http://nas.7bm.co:8073/admin/documents',
|
||||
baseUrl: 'http://nas.7bm.co:8873',
|
||||
documentUrl: 'http://nas.7bm.co:8873/docauditai/',
|
||||
uploadUrl: 'http://nas.7bm.co:8873/admin/documents',
|
||||
oauth: {
|
||||
serverUrl: 'http://10.79.112.85', // IDaaS服务器地址
|
||||
serverUrl: 'http://10.79.112.85', // IDaaS服务器地址
|
||||
clientId: '54d2a619fe5c81ae1250434c441fccccqMtKwh7H4fO',
|
||||
clientSecret: 'placeholder', // 需要替换为实际的Client Secret
|
||||
redirectUri: 'http://10.79.97.17/', // 回调地址
|
||||
@@ -162,6 +159,7 @@ const configs: Record<string, ApiConfig> = {
|
||||
oauth: {
|
||||
serverUrl: 'http://10.79.112.85', // IDaaS服务器地址
|
||||
clientId: '54d2a619fe5c81ae1250434c441fccccqMtKwh7H4fO',
|
||||
// clientSecret: 'VYk1AC5XIJEfnEXwyq0u9JEY3fi3byCfSD58zANGeb', // 需要替换为实际的Client Secret
|
||||
// ⚠️ 安全警告:clientSecret 不应该硬编码在代码中
|
||||
// 请在生产环境使用环境变量 OAUTH_CLIENT_SECRET
|
||||
clientSecret: 'placeholder', // 占位符,实际值从环境变量获取
|
||||
|
||||
@@ -0,0 +1,398 @@
|
||||
# 🚨 紧急:前端Dify集成问题修复指南
|
||||
|
||||
## 问题现状
|
||||
|
||||
**当前错误**:
|
||||
```javascript
|
||||
// ❌ 错误的Authorization头
|
||||
Authorization: Bearer app-lHn5EmeACIaLjG9yz0rYIFfM // 这是Dify API Key,不是JWT!
|
||||
|
||||
// ❌ 错误的user字段
|
||||
user: "user_34a1d450-6a24-4db7-b1e7-8dd7c0876f14:sess_3z84y7dtuhr" // UUID格式
|
||||
```
|
||||
|
||||
**导致的问题**:
|
||||
1. 无法加载历史对话记录(user不匹配)
|
||||
2. 对话没有按用户隔离(所有人共享对话)
|
||||
3. 安全问题(API Key暴露在前端)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 必须修改的3个地方
|
||||
|
||||
### 修改1: Authorization头 - 使用JWT替代Dify API Key
|
||||
|
||||
#### ❌ 旧代码(错误)
|
||||
```typescript
|
||||
// app/services/dify-client.server.ts 或类似文件
|
||||
const DIFY_API_KEY = "app-lHn5EmeACIaLjG9yz0rYIFfM";
|
||||
|
||||
async function callDifyAPI(endpoint: string, data: any) {
|
||||
const response = await fetch(`${DIFY_BASE_URL}${endpoint}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${DIFY_API_KEY}`, // ❌ 错误!暴露API Key
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
```
|
||||
|
||||
#### ✅ 新代码(正确)
|
||||
```typescript
|
||||
// app/services/dify-client.server.ts
|
||||
// 1. 移除DIFY_API_KEY配置
|
||||
// const DIFY_API_KEY = "..."; // 删除这行
|
||||
|
||||
// 2. 从用户session获取JWT
|
||||
import { getUserSession } from "~/api/login/auth.server";
|
||||
|
||||
async function callDifyAPI(request: Request, endpoint: string, data: any) {
|
||||
// 获取JWT
|
||||
const { frontendJWT } = await getUserSession(request);
|
||||
|
||||
if (!frontendJWT) {
|
||||
throw new Error("未登录,请先登录");
|
||||
}
|
||||
|
||||
// 使用JWT作为Authorization头
|
||||
const response = await fetch(`http://172.16.0.55:8000/dify${endpoint}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`, // ✅ 正确!使用JWT
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
```
|
||||
|
||||
### 修改2: 请求URL - 指向FastAPI代理而非直连Dify
|
||||
|
||||
#### ❌ 旧代码(错误)
|
||||
```typescript
|
||||
// 直连Dify API
|
||||
const DIFY_BASE_URL = "http://nas.7bm.co:12980/v1";
|
||||
|
||||
// 示例:获取会话列表
|
||||
const response = await fetch(
|
||||
`${DIFY_BASE_URL}/conversations?user=${user}&limit=100`,
|
||||
// ...
|
||||
);
|
||||
```
|
||||
|
||||
#### ✅ 新代码(正确)
|
||||
```typescript
|
||||
// 通过FastAPI代理访问Dify
|
||||
const API_BASE_URL = "http://172.16.0.55:8000"; // FastAPI地址
|
||||
|
||||
// 示例:获取会话列表
|
||||
const response = await fetch(
|
||||
`${API_BASE_URL}/dify/conversations?limit=100`, // ✅ 走/dify代理,不传user
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}` // ✅ 使用JWT
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### 修改3: user字段 - 完全移除,让后端自动添加
|
||||
|
||||
#### ❌ 旧代码(错误)
|
||||
```typescript
|
||||
// 生成UUID格式的user
|
||||
function generateUserId() {
|
||||
return `user_${crypto.randomUUID()}:sess_${randomString()}`;
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
const data = {
|
||||
query: "你好",
|
||||
user: generateUserId(), // ❌ 错误!UUID格式
|
||||
conversation_id: null,
|
||||
response_mode: "streaming",
|
||||
inputs: {}
|
||||
};
|
||||
```
|
||||
|
||||
#### ✅ 新代码(正确)
|
||||
```typescript
|
||||
// 完全不传user字段,后端会自动添加JWT的username
|
||||
const data = {
|
||||
query: "你好",
|
||||
// user字段完全不传! ✅ 正确
|
||||
conversation_id: null,
|
||||
response_mode: "streaming",
|
||||
inputs: {}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 完整的修改示例
|
||||
|
||||
### 示例1: 获取会话列表
|
||||
|
||||
#### ❌ 旧代码
|
||||
```typescript
|
||||
// app/routes/api.conversations.tsx
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const url = new URL(request.url);
|
||||
const user = url.searchParams.get("user") || generateUserId();
|
||||
const limit = url.searchParams.get("limit") || "100";
|
||||
|
||||
const response = await fetch(
|
||||
`http://nas.7bm.co:12980/v1/conversations?user=${user}&limit=${limit}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer app-lHn5EmeACIaLjG9yz0rYIFfM`, // ❌ Dify API Key
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return json(await response.json());
|
||||
}
|
||||
```
|
||||
|
||||
#### ✅ 新代码
|
||||
```typescript
|
||||
// app/routes/api.conversations.tsx
|
||||
import { getUserSession } from "~/api/login/auth.server";
|
||||
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
// 1. 获取JWT
|
||||
const { frontendJWT } = await getUserSession(request);
|
||||
|
||||
if (!frontendJWT) {
|
||||
return json({ error: "未登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
// 2. 调用FastAPI代理(不传user,后端自动添加)
|
||||
const url = new URL(request.url);
|
||||
const limit = url.searchParams.get("limit") || "100";
|
||||
|
||||
const response = await fetch(
|
||||
`http://172.16.0.55:8000/dify/conversations?limit=${limit}`, // ✅ 走代理
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`, // ✅ 使用JWT
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return json(await response.json());
|
||||
}
|
||||
```
|
||||
|
||||
### 示例2: 发送消息
|
||||
|
||||
#### ❌ 旧代码
|
||||
```typescript
|
||||
// app/routes/api.chat-messages.tsx
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
const body = await request.json();
|
||||
|
||||
const response = await fetch(
|
||||
`http://nas.7bm.co:12980/v1/chat-messages`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer app-lHn5EmeACIaLjG9yz0rYIFfM`, // ❌ Dify API Key
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: body.query,
|
||||
user: body.user || generateUserId(), // ❌ UUID格式
|
||||
conversation_id: body.conversation_id,
|
||||
response_mode: "streaming",
|
||||
inputs: body.inputs || {}
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
return new Response(response.body, {
|
||||
headers: { 'Content-Type': 'text/event-stream' }
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
#### ✅ 新代码
|
||||
```typescript
|
||||
// app/routes/api.chat-messages.tsx
|
||||
import { getUserSession } from "~/api/login/auth.server";
|
||||
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
// 1. 获取JWT
|
||||
const { frontendJWT } = await getUserSession(request);
|
||||
|
||||
if (!frontendJWT) {
|
||||
return json({ error: "未登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
// 2. 解析请求体
|
||||
const body = await request.json();
|
||||
|
||||
// 3. 调用FastAPI代理(不传user,后端自动添加)
|
||||
const response = await fetch(
|
||||
`http://172.16.0.55:8000/dify/chat-messages`, // ✅ 走代理
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`, // ✅ 使用JWT
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: body.query,
|
||||
// user字段完全不传 ✅ 后端自动添加
|
||||
conversation_id: body.conversation_id,
|
||||
response_mode: "streaming",
|
||||
inputs: body.inputs || {}
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
return new Response(response.body, {
|
||||
headers: { 'Content-Type': 'text/event-stream' }
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 检查清单
|
||||
|
||||
### 前端开发者必须检查的文件
|
||||
|
||||
1. **Dify客户端配置文件**
|
||||
- 位置:`app/services/dify-client.server.ts` 或类似
|
||||
- 检查:是否还有`DIFY_API_KEY`定义?(应该删除)
|
||||
- 检查:是否还有`DIFY_BASE_URL = "http://nas.7bm.co:12980"`?(应改为FastAPI地址)
|
||||
|
||||
2. **API路由文件**
|
||||
- 位置:`app/routes/api.*.tsx` 中所有与Dify相关的
|
||||
- 检查:所有`fetch`调用是否指向`http://172.16.0.55:8000/dify/*`?
|
||||
- 检查:所有`Authorization`头是否使用`frontendJWT`?
|
||||
|
||||
3. **user字段生成逻辑**
|
||||
- 搜索关键字:`generateUserId`, `user_`, `crypto.randomUUID`
|
||||
- 检查:是否还在生成UUID格式的user?(应该完全移除)
|
||||
|
||||
4. **环境变量配置**
|
||||
- 位置:`.env` 或 `.env.local`
|
||||
- 检查:是否还有`DIFY_API_KEY`或`NEXT_PUBLIC_APP_KEY`?(应该删除)
|
||||
|
||||
---
|
||||
|
||||
## 🧪 验证方法
|
||||
|
||||
修改完成后,使用浏览器开发者工具验证:
|
||||
|
||||
### 1. 检查Authorization头
|
||||
打开 Network 标签,找到Dify相关请求:
|
||||
|
||||
**✅ 正确的请求头**:
|
||||
```
|
||||
Request URL: http://172.16.0.55:8000/dify/conversations?limit=100
|
||||
Request Headers:
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... (JWT格式,很长)
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**❌ 错误的请求头**:
|
||||
```
|
||||
Request URL: http://nas.7bm.co:12980/v1/conversations?user=xxx
|
||||
Request Headers:
|
||||
Authorization: Bearer app-lHn5EmeACIaLjG9yz0rYIFfM (Dify API Key,很短)
|
||||
```
|
||||
|
||||
### 2. 检查请求体
|
||||
对于POST请求(如发送消息):
|
||||
|
||||
**✅ 正确的请求体**:
|
||||
```json
|
||||
{
|
||||
"query": "你好",
|
||||
"conversation_id": null,
|
||||
"response_mode": "streaming",
|
||||
"inputs": {}
|
||||
}
|
||||
```
|
||||
注意:**没有user字段**
|
||||
|
||||
**❌ 错误的请求体**:
|
||||
```json
|
||||
{
|
||||
"query": "你好",
|
||||
"user": "user_34a1d450-6a24-4db7-b1e7-8dd7c0876f14:sess_xxx",
|
||||
"conversation_id": null,
|
||||
"response_mode": "streaming",
|
||||
"inputs": {}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 检查后端日志
|
||||
修改后,后端日志应该显示:
|
||||
|
||||
```log
|
||||
[INFO] Dify请求用户: admin (ID: 5, 路径: conversations)
|
||||
[INFO] 自动添加user参数: admin
|
||||
[INFO] 查询参数: {'user': 'admin', 'limit': '100'}
|
||||
```
|
||||
|
||||
### 4. 检查Dify后台
|
||||
在Dify管理界面的对话列表中,应该看到:
|
||||
- 新对话的用户显示为:`admin`(或实际的username)
|
||||
- 不再是:`user_34a1d450...`
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 常见错误
|
||||
|
||||
### 错误1: 前端仍使用DIFY_API_KEY
|
||||
**症状**:Authorization头是`Bearer app-xxx`(短字符串)
|
||||
**解决**:删除所有`DIFY_API_KEY`定义,改用`frontendJWT`
|
||||
|
||||
### 错误2: 前端直连Dify
|
||||
**症状**:请求URL是`http://nas.7bm.co:12980/v1/...`
|
||||
**解决**:所有URL改为`http://172.16.0.55:8000/dify/...`
|
||||
|
||||
### 错误3: 仍在传递UUID格式的user
|
||||
**症状**:请求体包含`"user": "user_34a1d450..."`
|
||||
**解决**:完全删除user字段,不要传递
|
||||
|
||||
### 错误4: JWT获取失败
|
||||
**症状**:`frontendJWT`为`null`或`undefined`
|
||||
**解决**:检查`getUserSession`导入路径和session配置
|
||||
|
||||
---
|
||||
|
||||
## 📋 修改总结
|
||||
|
||||
| 项目 | 旧值 | 新值 |
|
||||
|------|------|------|
|
||||
| Authorization头 | `Bearer app-lHn5EmeACIaLjG9yz0rYIFfM` | `Bearer {frontendJWT}` |
|
||||
| 请求URL | `http://nas.7bm.co:12980/v1/*` | `http://172.16.0.55:8000/dify/*` |
|
||||
| user字段 | `user_34a1d450-...` | 完全不传(后端自动添加) |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 期望结果
|
||||
|
||||
修改完成后:
|
||||
- ✅ 每个用户只能看到自己的对话记录
|
||||
- ✅ Dify后台显示真实的username(如admin)
|
||||
- ✅ API Key不再暴露在前端
|
||||
- ✅ 所有对话按用户隔离
|
||||
- ✅ 历史对话记录正常加载
|
||||
|
||||
---
|
||||
|
||||
**紧急程度**: 🔴 高优先级
|
||||
**预计修改时间**: 30-60分钟
|
||||
**影响范围**: 所有Dify相关功能
|
||||
|
||||
**联系后端**: 如有疑问,请查看`docs/dify-frontend-user-field-guide.md`获取更多细节
|
||||
Reference in New Issue
Block a user