WITH ENCRYPTION 实为代码混淆而非加密,仅防随意查看,无法阻止有权限者获取明文;必须配合权限管控、逻辑下推、行级安全等措施才能真正保护业务逻辑。

WITH ENCRYPTION 不是加密,是混淆;它挡不住有权限的人,只防随手一查。 真正要保护业务逻辑,得靠权限收敛、逻辑下推、行级安全,而不是指望 sp_helptext 看不到就万事大吉。
CREATE 和 ALTER 都必须显式写 WITH ENCRYPTION
SQL Server 强制要求:一旦用 WITH ENCRYPTION 创建了存储过程,后续所有 ALTER PROCEDURE 语句也必须带上这个子句。否则直接报错:Cannot alter encrypted object without source text。
- 新建时漏写?建出来就是明文,
sys.sql_modules.definition可见,毫无防护 - 修改时在 SSMS 里右键“修改”,改完点执行——默认生成的是不带
WITH ENCRYPTION的ALTER,结果原过程被删掉重建为明文 - 已存在明文过程,想补加密?不行。只能先
DROP PROCEDURE,再CREATE PROCEDURE ... WITH ENCRYPTION,且必须确保无并发调用
加密失败的常见原因:静态解析失败
WITH ENCRYPTION 在 CREATE/ALTER 阶段就会做完整语法和对象解析,哪怕代码藏在 IF 0 = 1 BEGIN ... END 里也不放过。
- 引用了不存在的表、视图或函数,例如
SELECT * FROM nonexistent_table,会直接报错:Invalid object name 'nonexistent_table' - 跨数据库查询没加四部分命名(如
db2.schema.table),而当前上下文不是目标库,也会解析失败 - 使用了尚未创建的同义词(
SYNONYM)或未授权访问的系统视图,同样卡在创建阶段
加密后 definition 为空,但明文仍在多个地方可提取
sys.sql_modules.definition 字段确实变 NULL,sp_helptext 返回空行——但这只是“表面不可见”。实际明文仍可能暴露在:
- DAC 连接下查
sys.dm_exec_cached_plans+sys.dm_exec_sql_text,能拿到首次执行时解密进内存的原始文本 - 旧备份还原后,在未加密状态下重建对象,源码直接可见
- SQL Server 启动后首次执行该过程时,计划缓存中短暂存在明文(配合调试工具如
DBCC PAGE或 Profiler 可捕获)
也就是说,它对 DBA、运维、备份管理员完全无效;唯一作用是防止开发连不上生产库时,顺手敲个 sp_helptext 就看到工资公式。
真正该做的事:别把安全押在 WITH ENCRYPTION 上
加密选项解决不了权限滥用、误操作上线、敏感数据导出等问题。真正有效的做法是:
- 用最小权限原则控制
VIEW DEFINITION和ALTER权限,禁止非 DBA 账户直接查sys.sql_modules - 核心计算逻辑尽量下推到应用层或用证书加密列(
ENCRYPTBYCERT)处理敏感字段 - 启用行级安全(
CREATE SECURITY POLICY)限制用户只能看到自己数据,比隐藏 SQL 更治本 - 所有 DDL 变更走 CI/CD 流水线审批,禁用生产库直接执行
ALTER PROCEDURE
最容易被忽略的一点:很多人花时间写加密脚本、解密工具,却忘了检查 sys.dm_exec_sessions 中谁有 VIEW SERVER STATE 权限——这个权限足以绕过所有 WITH ENCRYPTION 的“防护”。

















