旧城梦呓 旧城梦呓
旧城梦呓

Dify + 企业微信

在企业微信中,通过使用智能机器人,完成数据库的查询,也就是通过企业微信智能机器人,使用自然语言查询数据库,实现 AI 驱动的数据检索。
由于种种原因,最终实现这个功能的最终架构如下:

员工提问(企业微信)
    ↓
企业微信智能机器人(API长连接模式)
    ↓
LangBot(消息中转桥梁,WebSocket连接)
    ↓
Dify 工作流(编排 AI 逻辑)
    ↓
db_query 插件(Dify 内置数据库查询工具)
    ↓
SSH 隧道(autossh,端口转发)
    ↓
内部数据库服务器(MySQL)

1 企业微信智能机器人创建(API长连接模式)

  1. 登录企业微信管理后台 (work.weixin.qq.com)。
  2. 进入「管理工具」→「智能机器人」,点击“创建机器人”。
  3. 选择“手动创建”,然后选择“API模式创建”。
  4. 在连接方式中,选择 “长连接”(不要填写任何回调 URL)。
  5. 创建完成后,记录以下三个关键信息:

    • 企业 ID (CorpID):在「我的企业」页面底部获取。
    • 机器人 ID (BotId):在机器人详情页获取。
    • 机器人 Secret (Secret):在机器人详情页生成并保存。

2 LangBot 部署与配置

LangBot 作为企业微信和 Dify 之间的“桥梁”,支持 WebSocket 长连接,无需公网域名。

2.1 部署 LangBot(Docker)

# 在  服务器上执行
docker run -d \
  --name langbot \
  -p 5300:5300 \
  -v /path/to/langbot/data:/app/data \
  --restart unless-stopped \
  ghcr.io/langbot-app/langbot:latest

访问 LangBot登录地址 进入 WebUI,默认账号密码见官方文档。

2.2 配置企业微信机器人

  1. 登录 LangBot WebUI。
  2. 进入「机器人」→「创建机器人」。
  3. 平台选择 “企业微信智能机器人”。
  4. 填入:

    • 企业 ID
    • 机器人 ID
    • 机器人 Secret
  5. 关闭「启用 Webhook」选项(即使用长连接)。
  6. 保存并启动机器人,状态应显示“已连接(WebSocket)”。

2.3 创建流水线并绑定 Dify

  1. 进入 LangBot「流水线」→「创建流水线」,命名如“数据库查询助手”。
  2. 在「AI 能力」中,将运行器设为 “Dify”。
  3. 填写:

    • Base URL:https://api.dify.ai/v1(或自部署地址)
    • API Key:从 Dify 工作流应用的「访问API」页面获取
    • 应用类型:选择 “工作流”
  4. 回到「机器人」编辑页面,将流水线绑定到该机器人。

3 Dify 工作流创建

  1. 登录 Dify,进入「工作室」→「创建空白应用」。
  2. 应用类型选择 “工作流”。
  3. 设计工作流,至少包含:

    • 开始节点:接收用户输入(如 query 变量)。
    • db_query 节点(稍后配置)。
    • 结束节点:输出查询结果。
  4. 发布工作流,并在「访问API」页面生成 API 密钥(用于 LangBot 配置)。

4 SSH 隧道建立

由于数据库服务器只能通过 SSH 公钥认证访问,且 Dify 运行在 Docker 容器中,我们在 Dify 服务器上建立一个 SSH 隧道,将数据库的 3306 端口映射到本地的 3307 端口,并让隧道监听所有接口(0.0.0.0),以便 Docker 容器可以访问。

4.1 测试 SSH 连通性

# 在 Dify 服务器上测试
ssh -i /env/server_key root@数据库服务器IP
# 应能直接登录(免密)

4.2 建立隧道(使用 autossh)

# 安装 autossh
sudo apt-get install autossh   # Ubuntu/Debian

# 后台运行隧道(监听所有接口)
autossh -f -M 0 -L 0.0.0.0:3307:127.0.0.1:3306 -i /env/server_key root@数据库服务器IP -N

参数说明:

  • -f:后台运行
  • -M 0:禁用内置监控端口(与 -N 配合)
  • -L 0.0.0.0:3307:127.0.0.1:3306:将本机所有接口的 3307 映射到数据库服务器的 3306
  • -N:不执行远程命令,仅端口转发

4.3 配置为 systemd 服务(开机自启)

创建服务文件 /etc/systemd/system/db-tunnel.service:

[Unit]
Description=SSH Database Tunnel
After=network.target

[Service]
User=root
ExecStart=/usr/bin/autossh -M 0 -L 0.0.0.0:3307:127.0.0.1:3306 -i /env/server_key root@数据库服务器IP -N
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

启动并启用:

sudo systemctl daemon-reload
sudo systemctl enable db-tunnel
sudo systemctl start db-tunnel
sudo systemctl status db-tunnel

4.4 验证隧道

# 查看端口监听
ss -tlnp | grep 3307
# 应显示 0.0.0.0:3307 处于 LISTEN 状态

# 宿主机测试
mysql -h 127.0.0.1 -P 3307 -u dify -p

5 Dify 中 db_query 插件配置

在 Dify 工作流中添加 db_query 节点(从插件市场安装),填写如下:

参数值
数据库类型MySQL
数据库地址172.16.1.252(宿主机内网 IP)
端口3307
用户名XXX
密码(数据库用户密码)
库名XXXX
SQL查询语句使用变量或固定语句(后续可结合 LLM 动态生成)
输出格式JSON

关键点:数据库地址必须填写宿主机的内网 IP,因为 Dify 容器内无法直接使用宿主机的 127.0.0.1。经过测试,172.16.1.252 是宿主机 eth0 的 IP。


6 数据库用户权限配置(MySQL)

6.1 创建用户并授予只读权限

最终我们使用 dify@localhost 用户(已从 % 收紧为 localhost),并使用 mysql_native_password 认证插件(兼容 pymysql)。

登录数据库服务器 MySQL(root 用户),执行:

-- 删除已存在的用户(可选)
DROP USER IF EXISTS 'XXX'@'localhost';
DROP USER IF EXISTS 'XXX'@'%';
DROP USER IF EXISTS 'XXX'@'127.0.0.1';

-- 创建用户(使用 mysql_native_password)
CREATE USER 'XXX(用户名)'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';

-- 授予 数据库XXX 的只读权限
GRANT SELECT ON `XXX(数据库名)`.* TO 'XXX(用户名)'@'localhost';

-- 刷新权限
FLUSH PRIVILEGES;

-- 验证
SELECT host, user FROM mysql.user WHERE user='XXX(用户名)';
SHOW GRANTS FOR 'XXX(用户名)'@'localhost';

6.2 权限收紧过程

  • 最初因 % 权限解决连接问题(因为匹配更宽松)。
  • 确认连接稳定后,逐步收紧为 localhost,并测试成功。

最终权限状态:

用户允许主机权限数据库
XXX(用户名)localhostSELECTXXX(数据库名)

7 Dify 容器网络验证

由于 Dify 运行在 Docker 中,需确保容器能访问宿主机的 3307 端口。

# 进入 Dify API 容器
docker exec -it docker-api-1 /bin/bash

# 测试 MySQL 连接
mysql -h 172.16.1.252 -P 3307 -u XXX(用户名) -p
# 输入密码,应能正常连接

如果连接失败,检查:

  • 隧道是否监听 0.0.0.0(ss -tlnp | grep 3307)。
  • 宿主机的防火墙是否放行 3307(一般本地端口默认开放)。

8 常见问题排查记录

8.1 bad permissions (SSH 私钥权限)

错误:Load key "/env/server_key": bad permissions

解决:

chmod 600 /env/server_key

8.2 Connection refused(容器访问宿主机端口)

原因:隧道只监听 127.0.0.1,Docker 容器无法访问。

解决:改为监听 0.0.0.0(-L 0.0.0.0:3307:...)。

8.3 Access denied for user 'dify'@'localhost'

原因:用户权限不足或认证插件不兼容。

解决步骤:

  • 使用 mysql_native_password 认证插件。
  • 授予 SELECT 权限。
  • 调整 Host 为 localhost(或 % 测试)。
  • 刷新权限。

8.4 语法错误 IDENTIFIED BY in GRANT(MySQL 8.0)

原因:MySQL 8.0 不再支持 GRANT ... IDENTIFIED BY。

解决:分步执行 CREATE USER 和 GRANT。

8.5 权限虽然授予但仍拒绝

原因:可能匹配到错误的 Host 记录。

解决:使用 DROP USER 清理所有同名用户,只保留一个正确的 Host。


9 最终配置清单

组件配置项值
企业微信机器人连接方式长连接(WebSocket)
BotId / Secret(实际值)
LangBot运行器Dify(工作流类型)
Dify Base URLhttps://api.dify.ai/v1(或自部署dify地址)
Dify API Key(工作流 API 密钥)
SSH 隧道监听地址0.0.0.0:3307
目标数据库服务器IP:3306
私钥路径/env/server_key(自定义路径)
启动方式systemd 服务 db-tunnel
Dify db_query数据库地址宿主机内网IP地址
端口3307
用户名XXX(用户名)
密码(强密码)
库名XXX(数据库名)
输出格式JSON
MySQL 用户用户名XXX(用户名)
允许主机localhost
认证插件mysql_native_password
全局权限USAGE
数据库权限SELECT ON XXX(数据库名).*

10 后续建议

  1. 定期修改数据库密码,并同步更新 db_query 插件配置。
  2. 监控隧道健康:建议使用 systemd 状态检查或监控脚本。
  3. 扩展工作流:结合 LLM 节点,实现自然语言到 SQL 的自动转换,提升用户体验。
  4. 日志审计:启用 Dify 操作日志,记录所有查询行为,便于安全审计。
  5. 权限最小化:根据实际需求,可进一步限制只能查询特定表或字段。

附录:关键命令速查

# SSH 隧道启动(前台测试)
autossh -M 0 -L 0.0.0.0:3307:127.0.0.1:3306 -i /env/server_key root@数据库IP -N

# 查看隧道状态
ss -tlnp | grep 3307
ps aux | grep autossh

# 进入 Dify 容器测试
docker exec -it docker-api-1 /bin/bash
mysql -h 172.16.1.252 -P 3307 -u dify -p

# MySQL 权限操作(示例)
CREATE USER 'XXX(用户名)'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';
GRANT SELECT ON `XXX(数据库名)`.* TO 'XXX(用户名)'@'localhost';
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'XXX(用户名)'@'localhost';
上一篇 Git 快速上手使用手册 下一篇 《饥荒联机版》专用服务器搭建

暂无评论

Ctrl + Enter 发送

还没有评论,来说点什么吧

© 2021-2026 旧城梦呓 All Rights Reserved.
鲁ICP备2021040936号-2
Theme Robes