mysql函数权限如何设置_mysql安全配置方法

2次阅读

mysql函数创建需同时满足:用户拥有CREATE ROUTINE和ALTER ROUTINE权限;log_bin_trust_function_creators=1或未启用binlog;函数须显式声明DETERMINISTIC、NO SQL或READS SQL DATA及SQL SECURITY。

mysql函数权限如何设置_mysql安全配置方法

MySQL 函数创建权限到底要哪些?

普通用户执行 CREATE FUNCTION 会直接报错:Error 1418 (HY000): this function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration,但这只是表象。真正卡住的是权限和全局配置双重限制。

必须同时满足:

  • 用户拥有 CREATE ROUTINE 权限(不是 CREATE FUNCTION —— 这个权限不存在)
  • 用户拥有 ALTER ROUTINE 权限(后续修改函数需要)
  • MySQL 启动时未设置 --log-bin,或已显式设置 log_bin_trust_function_creators=1

否则即使权限全开,也会因二进制日志安全机制被拒绝。

如何安全开启自定义函数支持?

不建议直接设 log_bin_trust_function_creators=1 后全局放行。更稳妥的做法是:

  • 仅在确需函数复制的主从环境中启用该参数,且只对可信账号授权
  • my.cnf 中添加:
    [mysqld] log_bin_trust_function_creators = ON
  • 修改后必须重启 MySQL(动态 SET 不生效)
  • 随后授予具体用户权限:

    GRANT CREATE ROUTINE, ALTER ROUTINE ON *.* TO 'dev_user'@'localhost';

注意:ON . 是全局级别;若只需某库,用 ON app_db.* 即可,但函数本身仍可跨库调用。

函数体里访问数据表,权限怎么算?

函数运行时的权限,取决于定义者(DEFINER) 而非调用者(INVOKER),这是关键误区。

  • 若定义为 DEFINER = 'admin'@'%',则函数内所有 select/INSERT 操作都以 admin 权限执行
  • 若定义为 SQL SECURITY INVOKER,则权限检查发生在调用时刻,依赖当前用户对目标表的权限

生产环境强烈建议显式声明:

CREATE FUNCTION get_user_name(uid int) RETURNS VARCHAR(50) READS SQL DATA SQL SECURITY DEFINER ...

否则默认是 DEFINER,但若定义者账号后来被删或密码过期,函数会直接失效,且错误提示极不直观(常表现为空结果或 NULL)。

为什么函数在命令行能跑,java 应用却报错?

常见于 JDBC 连接串未指定 allowMultiQueries=true 或未关闭 prepared statement 缓存,但更隐蔽的原因是:

  • MySQL 8.0+ 默认禁用 CREATE FUNCTION 的自动权限继承
  • 应用连接使用的账号可能没被显式授予 CREATE ROUTINE,即使它是 root 降权后的账号
  • 函数中用了 SELECT ... INTO 但目标变量未声明,错误被 JDBC 吞掉,只返回空结果

排查时先在 MySQL 客户端用同一账号执行:

SHOW GRANTS for CURRENT_USER;

确认输出中包含 CREATE ROUTINE;再检查函数体内所有表名是否带库名前缀(避免跨库时因权限粒度问题失败)。

函数权限的复杂性不在授权动作本身,而在于定义者语义、二进制日志策略、以及调用上下文的三重耦合。漏掉任意一环,都会表现为“明明给了权限却不能用”。

text=ZqhQzanResources