相关的文档10bet官方网站 下载本手册
PDF(美国高级主任)- 41.9 mb
PDF (A4)- 42.0 mb
手册页(TGZ)- 266.1 kb
手册页(Zip)- 376.0 kb
信息(Gzip)- 4.0 mb
信息(邮政编码)- 4.0 mb
本手册节选

MySQL 8.0参考手册/存储对象/存储对象访问控制

25.6存储对象访问控制

存储的程序(过程、函数、触发器和事件)和视图在使用前定义,在引用时在确定其权限的安全上下文中执行。适用于执行存储对象的权限由其控制定义者属性和SQL安全的特点。

DEFINER属性

存储对象定义可以包括定义者指定MySQL帐户的属性。的定义定义者属性时,默认对象定义者是创建它的用户。

下面的规则确定可以将哪些帐户指定为定义者属性:

  • 如果你有SET_USER_ID特权(或已弃用的特权超级特权),则可以将任何帐户指定为定义者属性。如果该帐户不存在,则会产生警告。此外,设置存储的对象定义者属性的帐户SYSTEM_USER特权,你必须拥有SYSTEM_USER特权。

  • 否则,唯一允许的帐户是您自己的,指定为字面或CURRENT_USERCURRENT_USER ().不能将定义器设置为任何其他帐户。

使用不存在的对象创建存储对象定义者Account创建了一个孤立对象,这可能会产生负面后果;看到孤儿存储对象

SQL的安全特性

对于存储例程(过程和函数)和视图,对象定义可以包含SQL安全值为的特征定义者调用程序指定对象是在定义程序上下文中执行还是在调用程序上下文中执行。如果定义省略了SQL安全特性,默认为定义上下文。

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

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

  • 在定义器安全上下文中执行的存储对象使用其命名的帐户的特权执行定义者属性。这些特权可能与调用用户的特权完全不同。调用方必须具有引用对象的适当权限(例如,执行调用存储过程或选择从视图中选择),但在对象执行期间,调用者的特权将被忽略,并且只有定义者帐户特权很重要。如果定义者帐户几乎没有特权,对象可以执行的操作也相应受到限制。如果定义者帐户是高度特权的(如管理帐户),对象可以执行强大的操作不管是谁调用它。

  • 在调用方安全上下文中执行的存储例程或视图只能执行调用方具有特权的操作。的定义者属性对对象执行没有影响。

例子

考虑以下存储过程,它是用SQL安全定义器在定义器安全上下文中执行:

CREATE DEFINER = 'admin'@'localhost' PROCEDURE 1() SQL SECURITY DEFINER BEGIN UPDATE t1 SET counter =计数器+ 1;结束;

的任何用户执行特权的p1可以使用调用声明。然而,当p1执行时,它在定义器安全上下文中执行,因此使用的权限执行“admin”@“localhost”,该帐户被命名为其定义者属性。此帐户必须具有执行特权的p1以及更新表的特权t1在对象体中引用。否则,该过程将失败。

现在考虑这个存储过程,它与p1除了它SQL安全特点是调用程序

CREATE DEFINER = 'admin'@'localhost' PROCEDURE p2() SQL SECURITY INVOKER开始更新t1 SET计数器=计数器+ 1;结束;

不像p1p2在调用方安全上下文中执行,因此具有调用方用户的特权,而不管定义者属性值。p2属性,则失败执行特权的p2或者是更新表的特权t1

孤儿存储对象

孤儿存储对象是指其定义者属性命名一个不存在的帐户:

  • 孤儿存储对象可以通过指定不存在的对象来创建定义者创建对象时的帐户。

  • 方法的执行可以使现有存储的对象成为孤立对象减少用户语句,删除对象定义者帐户,或重命名用户语句,用于重命名对象定义者帐户。

孤儿存储对象可能在以下方面存在问题:

  • 因为定义者Account不存在,如果在定义器安全上下文中执行,对象可能无法正常工作:

    • 对于存储的例程,如果在例程执行时出现错误SQL安全值是定义者但是定义者帐户不存在。

    • 对于触发器,在帐户实际存在之前发生触发器激活并不是一个好主意。否则,有关特权检查的行为是未定义的。

    • 对于事件,如果帐户不存在,则在事件执行时发生错误。

    • 类型引用视图时,将发生错误SQL安全值是定义者但是定义者帐户不存在。

  • 如果不存在,则该对象可能存在安全风险定义者帐户随后被重新创建,目的与对象无关。在本例中,是帐户采用对象和具有适当的特权,即使不打算这样做,也能够执行它。

从MySQL 8.0.22开始,服务器强加了额外的帐户管理安全检查,旨在防止(可能是无意中)导致存储对象成为孤儿的操作,或导致采用当前为孤儿的存储对象:

  • 减少用户如果要删除的任何帐户命名为定义者属性用于任何存储对象。(也就是说,如果删除帐户将导致存储的对象成为孤立的,则语句失败。)

  • 重命名用户如果要重命名的任何帐户被命名为定义者属性用于任何存储对象。(也就是说,如果重命名帐户会导致存储的对象成为孤立的,则语句失败。)

  • 创建用户如果要创建的任何帐户命名为定义者属性用于任何存储对象。(也就是说,如果创建帐户将导致帐户采用当前孤立的存储对象,则语句失败。)

在某些情况下,可能有必要故意执行这些帐户管理报表,即使它们在其他情况下会失败。要实现这一点,如果用户具有SET_USER_ID特权,该特权将覆盖孤立对象安全检查,语句成功并提示警告,而不是失败并提示错误。

要获得有关MySQL安装中用作存储对象定义器的帐户的信息,请查询INFORMATION_SCHEMA

这个查询确定了INFORMATION_SCHEMA表描述具有属性的对象定义者属性:

从信息schema中选择TABLE_SCHEMA, TABLE_NAME。column_name = ' definer '的列;+--------------------+------------+ | TABLE_SCHEMA | TABLE_NAME  | +--------------------+------------+ | 日常事件information_schema | | | information_schema | | | information_schema触发| | | information_schema |视图  | +--------------------+------------+

结果告诉您要查询哪些表以发现哪个存储对象定义者值存在和哪些对象有特定的定义者值:

  • 来识别定义者值存在于每个表中,使用这些查询:

    从information_schema.events中选择不同的定义器;从information_schema.routines中选择不同的定义器;从information_schema.triggers中选择不同的定义器;从information_schema.views中选择不同的定义器;

    查询结果显示如下:

    • 如果帐户存在,删除或重命名它会导致存储的对象成为孤立的。如果计划删除或重命名帐户,请考虑先删除其关联的存储对象或重新定义它们以使用不同的定义器。

    • 如果该帐户不存在,创建它会导致它采用当前孤立的存储对象。如果您计划创建帐户,请考虑是否应该将孤立对象与该帐户关联。如果不是,则重新定义它们以使用不同的定义符。

    要使用不同的定义器重新定义对象,可以使用改变事件改变观点若要直接修改定义者事件和观点的叙述。对于存储过程和函数以及触发器,必须删除对象并重新创建它以分配不同的定义者账户

  • 来识别哪些对象具有给定的定义者帐户,使用这些查询,将感兴趣的帐户替换为user_name@host_name

    从information_schema中选择event_schema, event_name。definer = '的事件user_name@host_name”;在information_schema中选择routine_schema, routine_name, routine_type。definer = '的例程user_name@host_name”;从information_schema中选择trigger_schema, trigger_name。definer = '的触发器user_name@host_name”;从information_schema中选择table_schema, table_name。definer = '的视图user_name@host_name”;

    例程表中,查询包括ROUTINE_TYPE列,使输出行区分是否定义者用于存储过程或存储函数。

    如果您正在搜索的帐户不存在,则这些查询所显示的任何对象都是孤儿对象。

风险最小化原则

为了最小化存储对象创建和使用的潜在风险,请遵循以下指导原则:

  • 不要创建孤立的存储对象;的对象定义者属性命名一个不存在的帐户。删除或重命名由?命名的帐户,不要导致存储的对象成为孤儿定义者任何现有对象的属性。

  • 对于存储的例程或视图,使用SQL安全调用程序在对象定义中,以便仅由具有适合该对象执行的操作的权限的用户使用。

  • 属性时创建定义上下文存储对象SET_USER_ID特权(或已弃用的特权超级Privilege),指定一个显式的定义者属性,该属性指定仅拥有该对象执行的操作所需权限的帐户。指定高度特权定义者只有在绝对必要时才考虑。

  • 管理员可以阻止用户创建指定高特权的存储对象定义者通过不授予他们SET_USER_ID特权(或已弃用的特权超级特权)。

  • 在编写定义上下文对象时应牢记,它们可能能够访问调用用户没有权限的数据。在某些情况下,可以通过不授予未授权用户特定权限来防止对这些对象的引用:

    • 属性的用户不能引用存储的例程执行它的特权。

    • 没有相应权限的用户不能引用视图(选择要从中选择,插入插入,等等)。

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

    • 触发器是通过访问与它相关联的表来激活的,即使是没有特殊权限的用户访问普通表。

    • 事件由服务器在预定的基础上执行。

    在这两种情况下,如果定义者帐户具有高度特权,对象可能能够执行敏感或危险的操作。如果创建对象的用户帐户撤销了创建对象所需的特权,则仍然如此。管理员在授予用户对象创建权限时应该特别小心。