• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 存储对象访问控制

    存储的程序(过程,函数,触发器和事件)视图是在使用前定义的,并且在引用时在确定其特权的安全上下文中执行。这些特权由其DEFINER属性和SQL SECURITY特征控制。

    • DEFINER属性
    • SQL安全特性
    • 例子
    • 风险最小化准则

    DEFINER属性

    所有存储的对象定义都可以包含一个DEFINER名为MySQL帐户的属性。如果定义忽略该DEFINER属性,则默认定义者是创建对象的用户。

    MySQL使用以下规则来控制用户可以在对象DEFINER属性中指定的帐户:

    • 如果您具有SET_USER_IDSUPER特权,则可以将任何帐户指定为DEFINER值,但是如果该帐户不存在,则会生成警告。另外,从MySQL 8.0.16开始,要将DEFINER存储对象的属性设置为具有SYSTEM_USER特权的帐户,您必须具有SYSTEM_USER特权。
    • 否则,唯一允许的帐户是您自己的帐户,可以按字面值或as CURRENT_USER或指定CURRENT_USER()。您不能将定义器设置为其他帐户。

    使用不存在的DEFINER帐户创建存储的对象可能会带来负面影响:

    • 对于存储的例程,如果SQL SECURITY值是,DEFINER但定义者帐户不存在,则在例程执行时发生错误。
    • 对于触发器,在帐户确实存在之前才进行触发器激活不是一个好主意。否则,关于特权检查的行为是不确定的。
    • 对于事件,如果该帐户不存在,则会在事件执行时发生错误。
    • 对于视图,如果SQL SECURITY值是,DEFINER但定义者帐户不存在,则在引用该视图时会发生错误。

    SQL安全特性

    存储的例程(过程和函数)和视图的定义可以包括SQL SECURITY一个值为DEFINERINVOKER用于指定对象是在定义者环境还是调用者环境中执行的特征。如果定义忽略SQL SECURITY特性,则默认为定义者上下文。

    触发器和事件没有SQL SECURITY特征,并且总是在定义器上下文中执行。服务器根据需要自动调用这些对象,因此没有调用用户。

    定义者和调用者安全上下文的区别如下:

    • 在定义者安全性上下文中执行的存储对象将以其DEFINER属性命名的帐户特权执行。这些特权可能与调用用户的特权完全不同。调用程序必须具有适当的特权才能引用该对象(例如,EXECUTE调用存储过程或SELECT从视图中选择),但是在对象执行期间,调用程序的特权将被忽略,只有DEFINER帐户特权才重要。如果该DEFINER帐户具有很少的特权,则相应地限制对象可以执行的操作。如果DEFINER帐户具有很高的特权(例如root帐户),无论对象是谁调用该对象都可以执行强大的操作
    • 在调用者安全上下文中执行的存储例程或视图只能执行调用者具有特权的操作。该DEFINER属性在对象执行期间不起作用。

    例子

    考虑以下存储过程,该存储过程声明SQL SECURITY DEFINER为在定义程序安全性上下文中执行:

    CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
    SQL SECURITY DEFINER
    BEGIN
      UPDATE t1 SET counter = counter + 1;
    END;
    

    任何具有EXECUTE特权的用户都p1可以使用CALL语句来调用它。但是,在p1执行时,它会在定义者安全性上下文中执行操作,并因此'admin'@'localhost'DEFINER属性中命名的帐户的特权执行。此帐户必须具有EXECUTE的权限p1,以及在UPDATE为表特权t1的对象身体内引用。否则,该过程将失败。

    现在考虑这个存储过程,p1除了它的SQL SECURITY特征是INVOKER

    CREATE DEFINER = 'admin'@'localhost' PROCEDURE p2()
    SQL SECURITY INVOKER
    BEGIN
      UPDATE t1 SET counter = counter + 1;
    END;
    

    与不同p1,会p2在调用者安全性上下文中执行,因此无论DEFINER属性值如何,都具有调用用户的特权。p2如果调用者缺少表的EXECUTE特权p2UPDATE表的特权,则失败t1

    风险最小化准则

    为了最大程度地减少创建和使用存储对象的潜在风险,请遵循以下准则:

    • 对于存储的例程或视图,请SQL SECURITY INVOKER尽可能在对象定义中使用,以便只有具有适合于对象执行的操作权限的用户才能使用它。
    • 如果在使用具有SET_USER_IDSUPER特权的帐户时创建定义者上下文存储的对象,请指定一个显式DEFINER属性,该属性命名一个仅拥有对象执行操作所需特权的帐户。DEFINER仅在绝对必要时指定高特权帐户。
    • 管理员可以DEFINER通过不授予用户“SET_USER_ID或”SUPER特权来阻止用户创建指定高特权帐户的存储对象。
    • 编写定义程序上下文对象时应牢记,它们可能能够访问调用用户没有权限的数据。在某些情况下,可以通过不授予未授权用户特定的特权来防止引用这些对象:

      • 没有存储EXECUTE特权的用户不能引用该存储例程。
      • 没有适当权限(SELECT不能从中选择,INSERT插入等等)的用户不能引用视图。

      但是,对于触发器和事件不存在这样的控件,因为它们始终在定义器上下文中执行。服务器根据需要自动调用这些对象。用户不直接引用它们:

      • 触发器通过访问与其关联的表来激活,即使没有特殊特权的用户也可以通过普通表进行访问。
      • 服务器按计划执行事件。

      在这两种情况下,如果该DEFINER帐户都具有很高的特权,则该对象可能能够执行敏感或危险的操作。如果从创建对象的用户帐户中撤消了创建对象所需的特权,则情况仍然如此。管理员在授予用户对象创建特权时应格外小心。