Files
leaudit-platform-frontend/docs/URGENT-前端必须修改.md
T
TanWenyan 63acabccc9 配置优化:切换到生产环境内网地址并添加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>
2025-10-30 11:14:43 +08:00

10 KiB
Raw Blame History

🚨 紧急:前端Dify集成问题修复指南

问题现状

当前错误

// ❌ 错误的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

旧代码(错误)

// 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();
}

新代码(正确)

// 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

旧代码(错误)

// 直连Dify API
const DIFY_BASE_URL = "http://nas.7bm.co:12980/v1";

// 示例:获取会话列表
const response = await fetch(
  `${DIFY_BASE_URL}/conversations?user=${user}&limit=100`,
  // ...
);

新代码(正确)

// 通过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字段 - 完全移除,让后端自动添加

旧代码(错误)

// 生成UUID格式的user
function generateUserId() {
  return `user_${crypto.randomUUID()}:sess_${randomString()}`;
}

// 发送消息
const data = {
  query: "你好",
  user: generateUserId(),  // ❌ 错误!UUID格式
  conversation_id: null,
  response_mode: "streaming",
  inputs: {}
};

新代码(正确)

// 完全不传user字段,后端会自动添加JWT的username
const data = {
  query: "你好",
  // user字段完全不传!  ✅ 正确
  conversation_id: null,
  response_mode: "streaming",
  inputs: {}
};

📝 完整的修改示例

示例1: 获取会话列表

旧代码

// 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());
}

新代码

// 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: 发送消息

旧代码

// 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' }
  });
}

新代码

// 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_KEYNEXT_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请求(如发送消息):

正确的请求体

{
  "query": "你好",
  "conversation_id": null,
  "response_mode": "streaming",
  "inputs": {}
}

注意:没有user字段

错误的请求体

{
  "query": "你好",
  "user": "user_34a1d450-6a24-4db7-b1e7-8dd7c0876f14:sess_xxx",
  "conversation_id": null,
  "response_mode": "streaming",
  "inputs": {}
}

3. 检查后端日志

修改后,后端日志应该显示:

[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获取失败

症状frontendJWTnullundefined 解决:检查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获取更多细节