mysql存储过程不支持源码加密,definer仅控制执行权限,无法隐藏逻辑;防止泄露须撤销show routine权限及information_schema.routines的select权限,或前移业务逻辑至应用层。

DEFINER 权限本身不能隐藏存储过程源代码,它只控制执行时的权限上下文,对 SHOW CREATE PROCEDURE 或查询 information_schema.ROUTINES 完全无效。
MySQL 没有机制能让 DEFINER 阻止用户查看过程定义——只要用户有 SELECT 权限访问 information_schema.ROUTINES,就能看到完整源码,无论 DEFINER 是谁、SQL SECURITY 设为 DEFINER 还是 INVOKER。
DEFINER 的真实作用仅限于:
- 决定存储过程内部语句以谁的权限运行(比如能否删某张表)
- 不影响“谁能看到源码”这个事实
所以试图靠改 DEFINER 'admin'@'localhost' 或加 SQL SECURITY DEFINER 来防代码泄露,是方向性错误。
真正能限制查看存储过程定义的操作只有权限控制
MySQL 提供了两个直接相关的权限项:
-
SHOW ROUTINE:控制是否允许执行SHOW CREATE PROCEDURE和SHOW CREATE FUNCTION -
SELECToninformation_schema.ROUTINES:控制是否能查到过程定义(因为information_schema.ROUTINES是一张视图,其ROUTINE_DEFINITION字段就存着源码)
要让普通用户看不到过程逻辑,必须:
-
REVOKE SHOW ROUTINE ON <em>.</em> FROM 'app_user'@'%'; - 确保该用户没有全局或数据库级的
SELECT权限(否则仍可能绕过,比如用SELECT ROUTINE_DEFINITION FROM information_schema.ROUTINES WHERE ROUTINE_NAME = 'xxx') - 若需保留部分权限,可建专用账号只授
EXECUTE,不给SELECT和SHOW ROUTINE
为什么 DEFINER + SQL SECURITY INVOKER 也不行
有人误以为设成 SQL SECURITY INVOKER 就能“隔离定义”,但这是混淆了执行权限和元数据可见性。
-
SQL SECURITY INVOKER只表示过程内语句按调用者权限执行(比如调用者没权限删表,过程里DROP TABLE就会失败) - 它完全不阻止调用者执行
SHOW CREATE PROCEDURE p1——只要该用户有SHOW ROUTINE权限,照样返回明文
你甚至可以验证:
- 用
root创建一个SQL SECURITY INVOKER过程 - 给
test_user授EXECUTE+SHOW ROUTINE -
test_user登录后执行SHOW CREATE PROCEDURE p1→ 源码完整可见
容易被忽略的关键点
-
SHOW ROUTINE是独立权限,默认不包含在SELECT或EXECUTE中,但很多初始化脚本会顺手开它,导致“以为限制了权限,其实没关掉查看入口” -
information_schema是系统库,它的访问控制依赖底层权限检查;只要用户有对应表的SELECT,就可能读到定义——哪怕没显式授过权(例如通过GRANT ALL ON <em>.</em>) - 如果用了代理用户(proxy user)或中间件连接池,要确认最终连接身份是否继承了不该有的权限,而不是只看应用配置的账号
真正难防的是有 DBA 权限的人,或者能连上实例并具备基础查询能力的任意账户。把逻辑移出数据库,才是唯一不依赖权限开关的解法。











