Featured image of post SQL Server 触发器调 Web 接口与 Navicat 密码恢复技巧

SQL Server 触发器调 Web 接口与 Navicat 密码恢复技巧

本文整理两个生产中「走偏门」但很实用的数据库技巧:① SQL Server 触发器调用 Web 接口(Ole Automation 拉取 HTTP 通知);② Navicat Premium 12+ 的密码加密算法与 NcxReader 一键解密。

为什么写这篇:两个看起来不相关的小技巧,生产里偶尔要用到——① SQL Server 触发器拉 WebHook 推送变更通知(典型场景:业务系统监听数据变更同步到第三方);② Navicat 的密码忘了或不方便找 DBA 要,需要从导出的 connections.ncx 文件里解出来。

适用读者:运维 DBA、后端开发、密码管理员。

前置知识:会用 SQL Server Management Studio、有 Python 基础。

⚠️ 本文仅做技术研究——所有密码相关示例均使用公开的开源工具与算法,不针对任何特定软件版本绕过授权。NcxReader 解密章节旨在让读者理解 Navicat 的"密码 = 透明存储"风险,从而推动生产环境改用专业密码管理工具。请勿用于非法用途。

目录

  1. SQL Server 触发器调用 Web 接口
  2. Navicat 密码加密原理
  3. NcxReader 一键解密

1. SQL Server 触发器调用 Web 接口

1.1 业务场景

某业务系统需要"主库一插入新数据,立即推送到第三方 API"——不想改业务代码(其他表也有类似需求),决定用触发器实现。

⚠️ 副作用警告:触发器里同步调 HTTP 会拖慢原表的 INSERT 性能——HTTP 慢、超时、第三方挂掉都会影响。建议配合异步队列(触发器只写队列表,外部消费者拉队列)使用。本文演示的是最简同步版

1.2 启用 Ole Automation Procedures

SQL Server 默认不开启 Ole Automation(用于在 T-SQL 里调用 COM 对象),需要先开:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
-- 1. 允许修改高级选项
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO

-- 2. 启用 Ole Automation Procedures
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO

-- 3. 验证
EXEC sp_configure 'Ole Automation Procedures';
GO

Ole Automation 仅在 Windows 上可用,Linux 上的 SQL Server 跑不了。

1.3 HTTP 请求的存储过程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
-- 创建辅助存储过程
CREATE PROCEDURE P_GET_HttpRequestData (
    @URL VARCHAR(500),
    @status INT = 0 OUT,
    @returnText VARCHAR(2000) = '' OUT
) AS
BEGIN
    DECLARE @object INT, @errSrc INT;

    -- 创建 COM 对象(Msxml2.ServerXMLHTTP.3.0)
    EXEC @status = SP_OACreate 'Msxml2.ServerXMLHTTP.3.0', @object OUT;
    IF @status <> 0 BEGIN
        EXEC SP_OAGetErrorInfo @object, @errSrc OUT, @returnText OUT;
        RETURN;
    END;

    -- open GET
    EXEC @status = SP_OAMethod @object, 'open', NULL, 'GET', @URL;
    IF @status <> 0 BEGIN
        EXEC SP_OAGetErrorInfo @object, @errSrc OUT, @returnText OUT;
        RETURN;
    END;

    -- setRequestHeader
    EXEC @status = SP_OAMethod @object, 'setRequestHeader',
         'Content-Type', 'application/x-www-form-urlencoded';

    -- send
    EXEC @status = SP_OAMethod @object, 'send', NULL;
    IF @status <> 0 BEGIN
        EXEC SP_OAGetErrorInfo @object, @errSrc OUT, @returnText OUT;
        RETURN;
    END;
END

1.4 创建触发器(AFTER INSERT)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- 1. 删旧触发器
DROP TRIGGER IF EXISTS [dbo].[hg_demo_notify_trigger];

-- 2. 建触发器
CREATE TRIGGER [dbo].[hg_demo_notify_trigger]
ON [dbo].[hg_demo]
AFTER INSERT
AS
BEGIN
    DECLARE @id VARCHAR(50), @name VARCHAR(50);
    DECLARE @url VARCHAR(4000), @t VARCHAR(10);

    -- 从 inserted 虚表里拿新插入的数据
    SELECT @id = id, @name = name FROM inserted;

    -- 拼 URL(这里要按第三方 API 协议拼)
    SET @t = '''';
    SET @url = 'http://internal.example.com/api/v1/demo/insert' +
               '?sql=insert into hg_demo(id,name)values(' +
               @t + @id + @t + ',' + @t + @name + @t + ')';

    -- 调用 HTTP
    EXECUTE P_GET_HttpRequestData @url;
END;

1.5 验证触发器

1
2
3
4
5
-- 1. 插入一条数据
INSERT INTO hg_demo (id, name) VALUES ('test_001', 'hello world');

-- 2. 检查目标端是否收到
-- 调第三方 API 的 admin 后台

1.6 关闭 Ole Automation(如果不用了)

1
2
3
4
5
6
7
8
9
-- 关闭
sp_configure 'show advanced options', 1;
RECONFIGURE;
sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE;

-- 关 advanced options
sp_configure 'show advanced options', 0;
RECONFIGURE;

1.7 性能与稳定性建议

问题修法
触发器拖慢 INSERT异步化:触发器只写队列表,后台 Job 拉队列调 HTTP
HTTP 超时卡死触发器加 timeout:SP_OASetProperty @object, 'setTimeouts', 5000, 5000, 10000, 10000
第三方 4xx/5xx 仍要写库触发器里加 BEGIN TRY ... END TRY / BEGIN CATCH ... END CATCH 捕获异常
HTTP 同步调易丢失上下文触发器里 SET NOCOUNT ON,避免消息干扰

1.8 异步化改造

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
-- 队列表
CREATE TABLE http_notify_queue (
    id BIGINT IDENTITY(1,1) PRIMARY KEY,
    payload NVARCHAR(MAX),
    created_at DATETIME DEFAULT GETDATE(),
    sent_at DATETIME NULL
);

-- 触发器只入队
CREATE TRIGGER [dbo].[hg_demo_async_trigger]
ON [dbo].[hg_demo]
AFTER INSERT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @id VARCHAR(50), @name VARCHAR(50);
    SELECT @id = id, @name = name FROM inserted;

    INSERT INTO http_notify_queue (payload)
    VALUES ('{"id":"' + @id + '","name":"' + @name + '"}');
END

-- 后台 Job(每 10 秒拉一批)
DECLARE @id BIGINT, @payload NVARCHAR(MAX);
DECLARE cur CURSOR FOR
    SELECT TOP 100 id, payload
    FROM http_notify_queue
    WHERE sent_at IS NULL
    ORDER BY id;

OPEN cur;
FETCH NEXT FROM cur INTO @id, @payload;
WHILE @@FETCH_STATUS = 0
BEGIN
    -- 调 HTTP(用 PowerShell 或 SQL Agent 的 Web Service Task)
    EXEC P_GET_HttpRequestData 'http://internal.example.com/api/notify?data=' + @payload;

    UPDATE http_notify_queue SET sent_at = GETDATE() WHERE id = @id;
    FETCH NEXT FROM cur INTO @id, @payload;
END
CLOSE cur;
DEALLOCATE cur;

2. Navicat 密码加密原理

2.1 connections.ncx 是什么

Navicat Premium 12+ 把所有连接信息存在两个地方:

  • 注册表(Windows):HKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers
  • JSON 文件(导出):connections.ncx

2.2 导出 ncx 文件

菜单:文件 → 导出连接 → 选 *.ncx 格式。

2.3 ncx 文件结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<Connections Ver="1.4">
  <Connection
    ConnectionName="localhost_5432-pg"
    ConnType="POSTGRESQL"
    Host="localhost"
    Port="5432"
    Database="postgres"
    UserName="postgres"
    Password="6E3CD79374732F89F047B5316FD28637"
    SavePassword="true"
    SettingsSavePath="C:\Users\me\Documents\Navicat\PostgreSQL\Servers\localhost_5432-pg"
    ...
  />
</Connections>

关键字段Password="6E3CD79374732F89F047B5316FD28637"——这是一段AES 加密的十六进制

2.4 加密算法

Navicat 12+ 使用 AES-128-CBC

  • 密钥:固定的 libcckeyi_dc(早期版本)或动态计算(新版)
  • IV:固定的 libcciv 字符串
  • 填充:PKCS7

不同 Navicat 版本密钥有差异——Navicat 11/12 用 libcckeyi_dc,Navicat 15+ 用 b'\x95\xd1\xdc\x7b\x9c\x53\x4f\xfb\x38\xa7\x1c\x8a\x47\x39\x33\x48' 等。


3. Navicat 密码安全建议(替代 NcxReader 解密)

⚠️ 本节为合规整改——上一版本"用 NcxReader 一键解密"的内容已全部删除

原因:解密工具的"一键回显明文"在生产环境等于把数据库明文密码公示给任何能拿到 connections.ncx 的人。即使只用于"自用恢复"也存在合规风险(密码出现在工具输出里、shell history 里、剪贴板里、屏幕录像里)。本节改为给运维/管理员的密码管理建议

3.1 风险评估:把 Navicat 密码当"明文"对待

从第 2 节的算法分析可以反推风险:

资产暴露场景风险等级
connections.ncx 文件备份到云盘、邮件转发、U 盘拷贝(拿到即拿到所有明文密码)
注册表 HKCU\Software\PremiumSoft\Navicat\Servers同事借电脑、镜像备份
屏幕/截屏录屏软件、远程协助
shell 历史(误用工具时)history 命令、运维审计

结论:Navicat 的"密码保护"只是防误看的提示框,不是安全机制。生产环境的数据库密码绝对不能依赖 Navicat 存

3.2 推荐方案:1Password / KeePass / Vault

生产推荐:所有数据库密码放进专业密码管理工具,Navicat 里只配连接信息(host/port/user),Password 字段留空——每次连手动从密码管理器复制粘贴。

1
2
3
4
5
# 1Password CLI 取密码(登录后)
op read "op://Prod/PostgreSQL/password"
# 复制到剪贴板(不进入 shell history)
op read "op://Prod/PostgreSQL/password" | pbcopy   # macOS
op read "op://Prod/PostgreSQL/password" | clip     # Windows
1
2
# HashiCorp Vault(自建场景)
vault kv get -field=password secret/postgres/prod

3.3 推荐方案:SSH 私钥 / IAM 临时凭证

云数据库/堡垒机场景——根本不用静态密码:

场景推荐方案
AWS RDSIAM 数据库身份验证(临时令牌,15 分钟过期)
Azure SQLAzure AD 身份验证
阿里云 RDSRAM 角色 + 临时 AccessKey
跳板机登录SSH 公私钥(Navicat 直接支持)
自建 PGpg_hba.confcert 认证(SSL 客户端证书)

优势没有静态密码 = 没有泄露

3.4 Navicat 自带的"安全"配置(仍然不够)

如果一定要在 Navicat 里存密码,至少做以下几项:

  1. Navicat → 工具 → 选项 → 常规 → 勾选"使用密码管理主密码"(让 Navicat 用一个 master password 二次加密)
  2. 不要导出 connections.ncx——导出 = 把二次加密绕过
  3. 不在 Navicat 里存 root / sa / 超级管理员密码——只存低权限的查询账号
  4. 定期 Rotate 密码——即使泄露也能在窗口期内失效

3.5 应急恢复(忘记密码的合法途径)

身份该怎么办
开发者本人联系 DBA 重置数据库密码(5 分钟搞定
DBA用 SQL 重置:ALTER USER app_user WITH PASSWORD 'new_pwd';(PG/MySQL) / ALTER LOGIN sa WITH PASSWORD = '...';(MSSQL)
离职人员不该有恢复密码的诉求——走正式交接,DBA 重置所有相关账号
审计/合规从密码管理器/堡垒机审计日志查——永远不查 Navicat

3.6 清理 Navicat 缓存的旧密码

1
2
3
4
5
# Windows:删除注册表里的所有 Navicat 密码
Remove-Item -Path "HKCU:\Software\PremiumSoft\Navicat\Servers\*" -Recurse -Force

# macOS:删除偏好设置
rm -rf ~/Library/Preferences/com.premiumsoft.navicat*

或者图形化:

1
Navicat → 连接属性 → 高级 → 清空 Password 字段

3.7 一次完整整改清单

按下面 5 步走,把团队的 Navicat 密码问题一次性根治

  1. 盘点:列出所有用 Navicat 管理数据库的同事 + 数据库清单
  2. 建库:1Password / Vault 建 Databases vault,按数据库分条目
  3. 轮换:所有数据库账号密码轮换一次(Navicat 旧密码全部作废)
  4. 配置:Navicat 只填连接信息,密码字段留空
  5. 文档:写一个 1 页 SOP:“新员工入职数据库访问申请流程”

经验总结

  1. 触发器调 Web API 慎用同步——同步触发器=业务稳定性的脆弱点
  2. Ole Automation 仅 Windows——Linux SQL Server 走 HTTP 需要装 SQL Server Machine Learning Services + Python
  3. Navicat 密码不是真加密——固定 IV + 公开密钥的 AES-CBC 等于明文,视为泄露
  4. 生产密码放 1Password / KeePass / Vault,不放 Navicat
  5. 尽量不存静态密码——云数据库走 IAM/AD 认证、自建 PG 走 SSL 证书
  6. 导出 ncx = 全公司数据库钥匙拱手送人——禁止导出,本地连接用密码管理器代填

使用 Hugo 构建
主题 StackJimmy 设计