在这个系列的 第 1 部分 中您学到,安装和操作 DB2 UDB V8.2 需要某些用户和组帐号。要记住的重点是,这些帐号是在 DB2 UDB 外的安全设施中定义的 —— 通常是操作系统。用户帐号管理(包括密码策略、命名约定和组定义)都是在这个外部设施上进行的。
图 1. 身份验证和授权
![身份验证和授权](https://i-blog.csdnimg.cn/blog_migrate/cd3bc9deecce8c8cedaf08c0d5b7fee7.png)
当提交 DB2 请求时,DB2 UDB 与这个外部设施进行交互,从而检验提供的用户 ID 和密码。这种交互称为身份验证,显示在 图 1 的下半部分。DB2 UDB 依赖于这个外部安全设施对用户进行身份验证,只有在身份验证成功时,才授予对 DB2 UDB 资源的访问权。
身份验证成功之后,DB2 UDB 必须判断用户是否具有执行操作所需的权限。这个过程称为授权,显示在 图 1 的上半部分。DB2 UDB 使用两种内部机制来判断授权是否成功 —— 权限级别和特权。在下面几节中,更详细地讨论这两个概念。
DB2 UDB 定义了一个权限级别层次结构,用于将一组预先确定的管理 权限授予用户帐号组。这些管理权限包括能够对数据库进行备份、迫使用户离开系统、查看表数据,等等。
有四个实例权限级别(SYSADM、SYSCTRL、SYSMAINT、SYSMON)和两个数据库权限级别(DBAMD、LOAD)。在实例级上定义的权限级别应用于这个实例中的所有数据库。
图 2. DB2 UDB 中的权限级别层次结构
![DB2 UDB 中的权限级别层次结构](https://i-blog.csdnimg.cn/blog_migrate/bdba0665fc0388b4756fe3269e2cf656.png)
权限级别按照 图 2 所示的层次结构进行安排。在这个层次结构的顶部是 SYSADM 权限级别,这是用户在 DB2 UDB 中可以拥有的最高的权限级别。具有 SYSADM 权限的用户可以执行所有可用的 DB2 操作。SYSCTRL 和 SYSMAINT 权限级别提供了 SYSADM 权限的子集,可以管理系统,但是不允许访问表中的任何数据。SYSMON 权限提供了使用数据库系统监视器的能力。DBADM 权限允许用户在一个实例中的特定数据库上执行管理任务,还允许完全访问这个数据库中的数据和对象。LOAD 权限允许用户运行 LOAD 实用程序,这是 DB2 UDB 的高速批量数据装载器。
表 1 总结了每个权限级别及其用途
表 1. 每个权限级别的总结
权限级别 | 说明和用途 |
---|---|
SYSADM |
|
SYSCTRL |
|
SYSMAINT |
|
SYSMON |
|
DBADM |
|
LOAD |
|
表 2 对比了每个权限级别允许的常见管理操作。
表 2. 每个权限级别允许的操作的比较
功能 | SYSADM | SYSCTRL | SYSMAINT | SYSMON | DBADM | LOAD |
---|---|---|---|---|---|---|
MIGRATE DATABASE | YES | NO | NO | NO | NO | NO |
GRANT/REVOKE DBADM | YES | NO | NO | NO | NO | NO |
UPDATE DBM CFG | YES | NO | NO | NO | NO | NO |
ESTABLISH/CHANGE SYSCTRL/SYSMAINT AUTHORITY | YES | NO | NO | NO | NO | NO |
UPDATE DB/NODE/DCS DIRECTORIES | YES | YES | NO | NO | NO | NO |
FORCE USERS OFF DATABASE | YES | YES | NO | NO | NO | NO |
CREATE/DROP DATABASE | YES | YES | NO | NO | NO | NO |
CREATE/DROP/ALTER TABLE SPACE | YES | YES | NO | NO | NO | NO |
RESTORE TO NEW DATABASE | YES | YES | NO | NO | NO | NO |
UPDATE DB CFG | YES | YES | YES | NO | NO | NO |
BACKUP DATABASE OR TABLE SPACE | YES | YES | YES | NO | NO | NO |
RESTORE TO EXISTING DATABASE | YES | YES | YES | NO | NO | NO |
PERFORM ROLLFORWARD RECOVERY | YES | YES | YES | NO | NO | NO |
START/STOP DATABASE INSTANCE | YES | YES | YES | NO | NO | NO |
RESTORE TABLE SPACE | YES | YES | YES | NO | NO | NO |
RUN TRACE | YES | YES | YES | NO | NO | NO |
OBTAIN MONITOR SNAPSHOTS | YES | YES | YES | YES | NO | NO |
CREATE/ACTIVATE/DROP EVENT MONITOR | YES | NO | NO | NO | YES | NO |
QUERY TABLE SPACE STATE | YES | YES | YES | NO | YES | YES |
PRUNE LOG HISTORY FILES | YES | YES | YES | NO | YES | NO |
QUIESCE INSTANCES | YES | YES | NO | NO | NO | NO |
QUIESCE DATABASES | YES | NO | NO | NO | YES | NO |
QUIESCE TABLE SPACE | YES | YES | YES | NO | YES | YES |
REORG TABLE | YES | YES | YES | NO | YES | NO |
RUN RUNSTATS UTILITY | YES | YES | YES | NO | YES | YES |
LOAD TABLE | YES | NO | NO | NO | YES | YES |
READ DATABASE TABLE DATA | YES | NO | NO | NO | YES | NO |
建立实例级权限的办法是,将在外部安全设施中定义的用户组赋给相关的实例级权限参数(SYSADM_GROUP、SYSCTRL_GROUP、SYSMAINT_GROUP、SYSMON_GROUP)。例如,如果希望用户帐号 KATE 具有 SYSMAINT 权限,那么可以将 KATE 放进 MAINT 组,然后将实例参数 SYSMAINT_GROUP 更新为 MAINT。这样,MAINT 组中的任何用户都将具有 SYSMAINT 权限。要从 KATE 那里撤消 SYSMAINT 特权,只需从 MAINT 组中删除她,或者将 SYSMAINT_GROUP 参数的值改为另一个不包含她的组。在后一种情况下,如果 MAINT 组的其他成员不是新组的成员,那么他们的 SYSMAINT 权限也会被撤消。
实例级权限参数可以从命令行或 Control Center 进行修改。例如,要将 SYSMAINT_GROUP 参数的值改为 MAINT,可以在命令行上执行以下命令:
update dbm cfg using SYSADM_GROUP MAINT
要让修改生效,必须使用以下两个命令重新启动 DB2 UDB 实例:
db2stop
db2start
要确认修改已经生效,可以通过执行以下命令来查看参数的值:
get dbm cfg
清单 1 中给出了前面的命令及其结果。还可以以相似的方式更新任何其他实例级权限参数。
清单 1. 使用命令行更新实例级权限参数
db2 => update dbm cfg using sysmaint_group maint DB20000I The UPDATE DATABASE MANAGER CONFIGURATION command completed successfully. db2 => db2stop 11/19/2005 21:19:03 0 0 SQL1064N DB2STOP processing was successful. SQL1064N DB2STOP processing was successful. db2 => db2start 11/19/2005 21:19:09 0 0 SQL1063N DB2START processing was successful. SQL1063N DB2START processing was successful. db2 => get dbm cfg Database Manager Configuration Node type = Enterprise Server Edition with local and remote clients ..... SYSADM group name (SYSADM_GROUP) = SYSCTRL group name (SYSCTRL_GROUP) = SYSMAINT group name (SYSMAINT_GROUP) = MAINT SYSMON group name (SYSMON_GROUP) = ..... |
要使用 Control Center 修改实例级权限参数,应该打开 Control Center,展开 All Systems 文件夹,展开目标系统,展开 Instances 文件夹,右击目标实例(在这个例子中是 DB2),并选择 Configure Parameters 项(见 图 3)。
图 3. 打开 Control Center 中的 configure parameters 对话框
![Control Center 中的 configure parameters 对话框](https://i-blog.csdnimg.cn/blog_migrate/5780aaafe1374559fcaa0fc795547a7c.png)
滚动参数列表(图 4)并找到相关的权限级别参数。点击参数值旁边的按钮来改变它的值。在图 4 所示的例子中,将 SYSMAINT_GROUP 参数的值改为 MAINT。
图 4. 在 Control Center 中修改 SYSMAINT_GROUP 参数
![Control Center 中的 DBM configuration 对话框](https://i-blog.csdnimg.cn/blog_migrate/aa5aa412b12131ca899a2606156344ea.png)
必须停止并重新启动实例,对参数的修改才会生效。在 Control Center 中,再次右击目标实例,并选择 Stop 项。如果提示对是否停止实例进行确认,那么点击 OK 按钮。再次右击目标实例,并选择 Start 项。然后就可以检查参数是否已经生效了。
在 Windows 上的默认 DB2 UDB 安装中,这些实例级权限参数默认为 NULL。这意味着任何属于本地 Administrators 组的用户帐号自动继承这些权限。因此,强烈建议明确地将这些参数的值改为特定的组名,以避免意外的/未授权的访问。在 Linux 和 UNIX 安装上,这不是个大问题,因为 NULL 值默认表示实例拥有者的主组,而这个组在安装之后默认情况下只包含实例拥有者的用户 ID。但是,明确地设置这些参数仍然是好的做法。
以相似方式作为数据库特权授予和撤消数据库级权限(比如 DBADM、CONNECT、CREATETAB 和 LOAD)。这在下一节中讨论。
实例权限级别这种机制用于将一组预先定义的管理权限授予一组用户帐号,而特权是明确分配给单独用户或组的,允许他们在数据库对象上执行特定操作(例如,创建和删除索引)。特权严格地定义了用户可以执行的任务。例如,用户可能具有读一个表的数据的特权,但是不能更新此数据。
图 5. DB2 UDB 权限和特权的层次结构
![各种权限和特权](https://i-blog.csdnimg.cn/blog_migrate/cbe8a7b5e4e85372e60e486137431f79.png)
图 5 显示 DB2 UDB 中不同的权限和特权级别。范围从表上的特权到模式和存储过程上的特权。图 5 的上部显示前一节描述的实例权限级别。注意 SYSADM 和 DBADM 权限自动获得虚线下面对于某个数据库的所有权限和特权。
表 3 总结了对于用户或用户组可以授予和撤消的数据库权限类型。只有具有 SYSADM 或 DBADM 权限的用户可以授予和撤消这些权限。
表 3. 数据库级权限的总结
数据库权限 | |
---|---|
CONNECT | 允许用户连接数据库 |
BINDADD | 允许用户在数据库中创建新的包 |
CREATETAB | 允许用户在数据库中创建新的表 |
CREATE_NOT_FENCED | 允许用户注册定义为 NOT FENCED 的用户定义函数(UDF)或存储过程 |
IMPLICIT SCHEMA | 允许用户在尚不存在的模式中创建对象(它自动地创建模式)* |
QUIESCE_CONNECT | 允许用户连接处于 quiesced 状态的数据库 |
CREATE_EXTERNAL_ROUTINE | 允许用户注册外部例程(用 C 和 Java 等外部语言编写的例程) |
*SYSIBM 成为隐式创建的模式的所有者,PUBLIC 组被授予在这个模式中创建对象的特权。
表 4 总结了对于用户或用户组可以授予和撤消的惟一一种表空间特权(USE)。USE 特权不能对 SYSCATSPACE 或任何系统临时表空间使用。
表 4. 表空间特权的总结
表空间特权 | |
---|---|
USE | 允许用户在指定的表空间中创建表 |
表 5 总结了对于用户或用户组可以授予和撤消的模式特权类型。
表 5. 模式特权的总结
模式特权 | |
---|---|
CREATEIN | 允许用户在模式中创建对象 |
ALTERIN | 允许用户在模式中修改对象 |
DROPIN | 允许用户从模式中删除对象 |
表 6 总结了对于用户或用户组可以授予和撤消的表/视图特权。
表 6. 表和视图特权的总结
表/视图特权 | |
---|---|
CONTROL | 授予用户在表和视图上的所有特权,以及将这些特权(除了 CONTROL)授予别人 |
ALTER | 允许用户在表中添加列、在表和它的列上添加或修改注释、添加主键或惟一约束以及创建或删除表检查约束 |
DELETE | 允许用户从表或视图中删除行 |
INDEX | 允许用户在表上创建索引 |
INSERT | 允许用户在表或视图中插入数据 |
REFERENCES | 允许用户创建和删除外键,这需要指定关系中的父表 |
SELECT | 允许用户从表或视图中检索行、在表上创建视图以及运行 EXPORT 实用程序 |
UPDATE | 允许用户修改表、视图或者表或视图中某些列中的数据;用户可以只在特定列上具有这种特权 |
表 7 总结了对于用户或用户组可以授予和撤消的惟一一种索引特权(CONTROL)。
表 7. 索引特权的总结
索引特权 | |
---|---|
CONTROL | 允许用户删除索引 |
表 8 总结了对于用户或用户组可以授予和撤消的包特权类型。“静态和动态 SQL 考虑因素” 一节更详细地讨论包概念。
表 8. 包特权的总结
包特权 | |
---|---|
CONTROL | 允许用户重新绑定、删除或执行包,以及将这些特权(除了 CONTROL)授予别人 |
BIND | 允许用户重新绑定现有的包 |
EXECUTE | 允许用户执行包 |
表 9 总结了对于用户或用户组可以授予和撤消的惟一一种例程特权(EXECUTE)。
表 9. 例程特权的总结
例程特权 | |
---|---|
EXECUTE | 允许用户调用例程,从例程创建函数(只应用于函数),以及在任何 DDL 语句(比如 CREATE VIEW、CREATE TRIGGER 或定义约束时)中引用例程 |
表 10 总结了对于用户或用户组可以授予和撤消的序列特权类型。
表 10. 序列特权的总结
序列特权 | |
---|---|
USAGE | 允许用户对序列使用 NEXTVAL 和 PREVVAL 表达式 |
ALTER | 允许用户使用 ALTER SEQUENCE 语句修改序列属性 |
与实例级权限相似,可以使用命令语法或 Control Center 授予和撤消特权。要想授予或撤消特权,必须有数据库连接。图 6 显示表和视图特权的 GRANT 语句的语法图。其他数据库对象的 GRANT 语句语法是相似的,请参考 DB2 UDB 文档。
图 6. 表和视图的 GRANT 语句语法图
![表和视图的 GRANT 语句语法图](https://i-blog.csdnimg.cn/blog_migrate/94b3229088879e438bc43d2aa4a0c4e8.png)
例如,要使用 GRANT 语句向用户 JEFF 授予 ACCOUNT 表的 INSERT 特权,那么发出以下语句:
GRANT INSERT ON TABLE account TO USER jeff
要向 SALESREPS 组授予 CUSTOMER 表的 SELECT 特权,那么发出以下语句:
GRANT SELECT ON TABLE customer TO GROUP salesreps
在向用户或组授予权限和特权时必须小心,因为 DB2 UDB 允许将这些特权授予不存在的帐号。如果以后创建了同名的帐号,那么这个帐号会自动获得以前授予的所有权限和特权。
还可以使用 Control Center 授予特权,办法是展开 All Databases 文件夹,展开目标数据库,展开包含感兴趣的数据库对象的文件夹,右击这个对象,并选择 Privileges 项。在 图 7 中,展开 SAMPLE 数据库中的 Tables 文件夹,右击 EMPLOYEE 表并选择 Privileges 项。
图 7. Control Center 中的表特权对话框
![Control Center 中的表特权对话框](https://i-blog.csdnimg.cn/blog_migrate/9116a62374c4cd946565adea162ed442.png)
在表特权对话窗口中,根据要向用户还是组授予特权,选择 User 或 Group。如果用户/组不在列表中,那么点击 Add User 或 Add Group 按钮添加用户或组。通过点击适当特权的下拉框并选择 Yes、No 或 Grant,从而指定应该向用户或组授予哪些特权。选择 Yes 意味着应该授予特权,选择 No 意味着应该不授予特权,选择 Grant 意味着应该授予此特权和向其他用户/组授予此特权的特权。点击 Grant All 按钮向指定用户或组授予所有可用的特权。点击 Revoke All 按钮从指定用户或组撤消所有可用的特权。
在 图 7 中可以看到,用户 MARK 只被授予 EMPLOYEE 表上的 INSERT 特权,这意味着 MARK 只能在这个表中插入数据,不能读或更新它。当然,这假设 MARK 不是具有这些特权或 SYSADM/DBADM 权限的组的成员。
在上面的例子或 GRANT 语句语法图中可以看出,可以分别使用 TO USER 或 TO GROUP 子句指定是向用户还是向组授予特权。如果没有指定这两个子句之一,但是指定的名称在操作系统中只定义为组,那么假设是 GROUP。如果指定的名称在操作系统中只定义为用户,或者没有定义,那么假设是 USER。如果指定的名称在操作系统中同时定义为用户和组,那么返回一个错误。作为最佳实践,我们建议在 GRANT 语句中总是包含 TO USER 或 TO GROUP 子句,以避免任何二义性。
DB2 UDB 在内部使用一个伪组 PUBLIC,可以对它授予和撤消特权。PUBLIC 实际上并不是外部安全设施中定义的一个组,而是一种向成功经过身份验证的用户分配特权的方式。可以对 PUBLIC 组授予和撤消特权,就像对其他组一样。例如,要从 PUBLIC 组撤消 IMPLICIT_SCHEMA 权限,可以发出以下语句:
REVOKE IMPLICIT_SCHEMA ON DATABASE FROM PUBLIC
重要的是,要理解向 PUBLIC 组授予特权的安全影响。任何提供了有效用户 ID 和密码的用户都能够执行 PUBLIC 组有权执行的操作。
许多数据库对象特权还允许在 GRANT 语句中包含 WITH GRANT OPTION 子句。这使您能够将一种特权授予用户或组,同时使用户或组的成员能够将同一特权授予别的用户/组。例如,以下语句将 ACCT 模式上的 ALTERIN、CREATEIN 和 DROPIN 特权授予组 G1,同时允许组 G1 的成员将这些特权授予别的用户或组:
GRANT ALTERIN, CREATEIN, DROPIN ON SCHEMA ACCT TO GROUP G1 WITH GRANT OPTION
WITH GRANT OPTION 只能用于包、例程、模式、表、视图和表空间的 GRANT 语句。
REVOKE 语句用于撤消以前授予的特权。图 8 显示表和视图的 REVOKE 语句的语法图。同样,其他数据库对象的 REVOKE 语法是相似的,请参考 DB2 UDB 文档。
图 8. 表和视图的 REVOKE 语句语法图
![表和视图的 REVOKE 语句语法图](https://i-blog.csdnimg.cn/blog_migrate/d79cb92377efef1f727fbcd1ce860427.png)
例如,要从用户 JEN 撤消 STAFF 表上的 ALTER 特权,可以发出以下语句:
REVOKE ALTER ON TABLE staff FROM USER jen
要从 JEN 撤消 STAFF 表上的所有特权,可以发出以下语句:
REVOKE ALL PRIVILEGES ON TABLE staff FROM USER jen
还可以使用 Control Center 撤消特权,操作方式与授予特权相似。只需重新打开对象特权对话窗口,如前面的 图 7 所示。要撤消一种特权,只需将此特权的下拉列表改为 NO,或者点击 Revoke All 按钮撤消与此对象相关的所有特权。
要撤消数据库对象上的特权,必须具有 DBADM 权限、SYSADM 权限或此对象上的 CONTROL 特权。注意,拥有 WITH GRANT OPTION 特权并不足以撤消这一特权。要从另一个用户撤消 CONTROL 特权,必须具有 SYSADM 或 DBADM 权限。
从用户或组撤消特权是撤消其他任何帐号授予他的特权。但是从用户或组撤消特权并不撤消这个用户/组授予别的帐号的同一特权。例如,假设用户 BEN 将 SELECT WITH GRANT OPTION 授予用户 RICK,然后 RICK 将 SELECT 授予用户 RAVI 和 CHRIS。如果以后 BEN 从 RICK 撤消了 SELECT 特权,那么 RAVI 和 CHRIS 仍然拥有 SELECT 特权。
还有一种情况:希望将一种特权授予一个组,然后只从这个组中的一个成员撤消这一特权。但是,不能撤消并未明确授予的特权。在这种情况下,有两种办法:
- 可以从这个组中删除这个成员;或者创建一个只包含组中其他成员的新组,并将特权授予这个新组。
- 可以从这个组撤消特权,然后向组的各个成员分别授予特权。
也使用 GRANT 语句将数据库级权限(比如 DBADM、LOAD 和 CREATETAB)授予用户或组。例如,以下语句将 DBADM 权限授予用户 SALLY:
GRANT DBADM ON DATABASE TO USER sally
以下语句将 LOAD 权限授予组 MAINT:
GRANT LOAD ON DATABASE TO GROUP maint
如果 LOAD 操作定义为 REPLACE,那么具有 LOAD 权限的用户还需要 INSERT 特权(为了将数据装载到表中)和 DELETE 特权。
要撤消数据库级权限,使用 REVOKE 语句。例如,要从组 MAINT 撤消 LOAD 权限,可以发出以下语句:
REVOKE LOAD ON DATABASE FROM GROUP maint
在某些情况下,当用户创建一个数据库对象(比如表或包)时,或者授予 DBADM 权限级别时,数据库管理器会隐式地将某些特权授予用户。重要的是,要了解授予了哪些隐式特权以及这些隐式特权的安全影响。表 11 总结了授予隐式特权的情况。
表 11. 对于不同操作授予的隐式特权的总结
操作 | 向执行此操作的用户授予的隐式特权 |
---|---|
创建新数据库 |
|
授予 DBADM 权限 |
|
模式 |
|
创建对象(表、索引、包) |
|
创建视图 |
|
例如,假设最初将 DBADM 权限授予用户 PAUL,以后决定撤消此权限。要从 PAUL 撤消 DBADM 权限,可以使用以下语句:
REVOKE DBADM ON DATABASE FROM USER paul
在执行这个命令之后,PAUL 不再拥有 DBADM 权限;但是,他仍然拥有数据库上的 GRANT、BINDADD、CONNECT、CREATETAB、CREATE_EXTERNAL_ROUTINE、CREATE_NOT_FENCED_ROUTINE、IMPLICIT_SCHEMA、LOAD 和 QUIESCE_CONNECT 权限,这些权限是原来将 DBADM 权限授予 PAUL 时隐式授予的。需要从 PAUL 明确地撤消这些权限。
一种好的安全实践是,在创建新数据库之后,明确地撤消隐式授予 PUBLIC 的许多特权。这可以保护系统,确保只有应该访问数据库的用户才能这么做。
如果在编译时一个 SQL 语句的语法是完全已知的,那么这个语句就称为静态 SQL。反之就是动态 SQL 语句,其语法直到运行时才知道。
在静态和动态 SQL 之间,处理特权的方式有一些差异。这些差异之一是如何处理组成员关系。一般来说,只对于动态 SQL 和非数据库对象授权(比如实例级命令和实用程序),需要考虑组成员关系。这种一般规则的一个例外发生在特权被授予 PUBLIC 时;在这种情况下,在处理静态 SQL 时也考虑组成员关系。
另一个差异是实际进行授权的时间。如果用静态 SQL 语句编写一个程序,那么必须先在数据库中创建包(包含 SQL 语句的优化且可执行形式的数据库对象),然后相关的程序才能执行包中包含的 SQL 语句。对静态 SQL 的授权发生在编译时或绑定时。在运行时,用户只需要有包上的 EXECUTE 特权,就能够执行其中的语句。这意味着用户不能直接访问底层数据库对象。对底层数据库对象的访问只能通过包中的特定语句进行。对于动态 SQL 语句,授权针对每个语句进行。执行语句的用户必须具有适当的特权,才能在运行时执行语句,特权可以是明确授予他们的,也可以是通过组成员关系授予的。
例如,假设在一个嵌入式 SQL 应用程序中有以下的静态 SQL 语句:
EXEC SQL SELECT col INTO :hostvar FROM table123;
假设包含这个语句的应用程序文件已经预先编译了,产生了绑定文件 sampleapp.bnd
。如果开发人员 BARBARA 希望将这个文件绑定到数据库(因此创建一个包),那么她需要具有 TABLE123 上的 SELECT 特权,才能成功执行 BIND 命令。这个规则有一个例外,即如果 PUBLIC 组已经被授予了这个特权,那么就不需要明确授予她这个特权。BARBARA 还需要 BINDADD 权限(如果这是一个新的包)或 BIND 特权(如果这是一个现有的包,她希望将它重新绑定到数据库,例如因为数据库统计值最近更新了)。
包也可能包含动态 SQL,在这种情况下,需要的特权取决于在对包进行预编译或绑定到数据库时 RECOMPILE/BIND 命令的 DYNAMICRULES 子句所指定的值。如果包是使用 DYNAMICRULES RUN(默认值)绑定的,那么要想使用其中的动态 SQL,运行动态 SQL 应用程序的用户必须具有发出每个 SQL 请求所需的特权,以及包上的 EXECUTE 特权。特权可以被授予用户的 ID、用户所在的任何组或 PUBLIC。
如果应用程序是使用 DYNAMICRULES BIND 选项绑定的,那么 DB2 UDB 将包所有者的用户 ID 与应用程序包关联起来。这使运行这个应用程序的任何用户能够继承与包所有者的用户 ID 相关联的特权。
例如,假设以上例子中的应用程序文件也包含动态 SQL,如 清单 2 所示:
清单 2. 一个嵌入式 SQL 应用程序中的动态 SQL
EXEC SQL BEGIN DECLARE SECTION; char hostVarStmt[50]; short hostVarDeptnum; EXEC SQL END DECLARE SECTION; strcpy(hostVarStmt, "DELETE FROM org WHERE deptnum = ?"); EXEC SQL PREPARE Stmt1 FROM :hostVarStmt; hostVarDeptnum = 15; EXEC SQL EXECUTE Stmt1 USING :hostVarDeptnum; |
如果 BARBARA 希望将同一个绑定文件绑定到数据库,那么她需要 BINDADD 权限(如果这是一个新的包)或 BIND 特权(如果这是一个现有的包)。因此,假设 BARBARA 使用以下的 BIND 命令绑定这个文件:
BIND sampleapp.bnd QUALIFIER u1 OWNER u2 DYNAMIC RULES RUN
在这个例子中,所有未限定的 SQL 语句(即没有使用模式名限定其中的数据库对象的语句)会使用模式 U1。因为使用了 OWNER 子句,用户 U2 会拥有这个包。因为 BARBARA 指定了 DYNAMIC RULES RUN 子句,所以会检查运行这个应用程序(执行这个包)的用户是否具有执行动态 SQL 的特权。
但是,如果 BARBARA 使用以下的 BIND 命令绑定这个文件,那么会检查包的所有者是否具有执行动态 SQL 的特权:
BIND sampleapp.bnd QUALIFIER u1 OWNER u2 DYNAMIC RULES BIND
在这个例子中,包的所有者被指定为 U2。因此,在运行时检查用户 U2 的特权,而不是检查运行应用程序的用户的特权。
EXECUTE 特权应用于数据库中所有类型的例程,包括函数、过程和方法。用户一旦被授予一个例程的 EXECUTE 特权,他就可以调用这个例程,从例程创建函数(只应用于函数),以及在任何 DDL 语句(比如 CREATE VIEW 或 CREATE TRIGGER)中引用例程。对于这个例程中访问的对象,不需要具有对应的特权。
DB2 UDB 将关于特权的信息存储在七个系统编目视图中:
- SYSCAT.DBAUTH - 数据库特权
- SYSCAT.COLAUTH - 表和视图列特权
- SYSCAT.INDEXAUTH - 索引特权
- SYSCAT.PACKAGEAUTH - 包特权
- SYSCAT.SCHEMAAUTH - 模式特权
- SYSCAT.TABAUTH - 表和视图特权
- SYSCAT.TBSPACEAUTH - 表空间特权
可以像查询任何其他视图一样查询这些视图。例如,要查明用户 EMMA 拥有哪些表特权,可以发出 清单 3 所示的命令:
清单 3. 查询 SYSCAT.TABAUTH 视图来了解特权信息
SELECT substr(grantor,1,8) AS grantor, SUBSTR(grantee,1,8) AS grantee, granteetype AS gtype, SUBSTR (tabschema,1,8) AS schema, SUBSTR (tabname,1,8) AS tabname, controlauth AS ctl, alterauth AS alt, deleteauth AS del, indexauth AS idx, insertauth AS ins, selectauth AS sel, refauth AS ref, updateauth AS upd FROM syscat.tabauth WHERE grantee = 'EMMA' GRANTOR GRANTEE GTYPE SCHEMA TABNAME CTL ALT DEL IDX INS SEL REF UPD ------- -------- ----- -------- -------- --- --- --- --- --- --- --- --- INST1 EMMA U INST1 TABLE1 Y G G G G G G G |
被授权者类型(GTYPE)‘U’ 意味着被授权者(拥有此特权的帐号)是一个用户帐号。GTYPE 值 ‘G’ 意味着被授权者是一个组帐号。在其他列中,‘Y’ 意味着拥有此特权,‘N’ 意味着不拥有此特权,‘G’ 意味着拥有此特权并可以授予其他人。在 清单 3 中,可以看出用户 EMMA 具有表 TABLE1 上的 CONTROL 特权,以及所有其他可用的表特权,包括将这些特权授予其他人的能力。
要查明具有特权的所有帐号,可以查询每个系统编目视图并使用 UNION 操作符将结果组合在一起,如 清单 4 所示:
清单 4. 判断具有特权的所有授权名称
SELECT DISTINCT GRANTEE, GRANTEETYPE, 'DATABASE' FROM SYSCAT.DBAUTH UNION SELECT DISTINCT GRANTEE, GRANTEETYPE, 'TABLE ' FROM SYSCAT.TABAUTH UNION SELECT DISTINCT GRANTEE, GRANTEETYPE, 'PACKAGE ' FROM SYSCAT.PACKAGEAUTH UNION SELECT DISTINCT GRANTEE, GRANTEETYPE, 'INDEX ' FROM SYSCAT.INDEXAUTH UNION SELECT DISTINCT GRANTEE, GRANTEETYPE, 'COLUMN ' FROM SYSCAT.COLAUTH UNION SELECT DISTINCT GRANTEE, GRANTEETYPE, 'SCHEMA ' FROM SYSCAT.SCHEMAAUTH UNION SELECT DISTINCT GRANTEE, GRANTEETYPE, 'SERVER ' FROM SYSCAT.PASSTHRUAUTH ORDER BY GRANTEE, GRANTEETYPE, 3 |
还可以使用 Control Center 查明一个用户或组具有的所有特权。操作方法是,打开 Control Center,展开 All Databases 文件夹,展开目标数据库,展开 Users and Group Objects 文件夹,展开 DB Users 或 DB Groups 文件夹,并双击感兴趣的用户或组的行。在 图 9 中,打开了 SAMPLE 数据库中用户 MARK 的特权对话框。选择 Database 选项卡,会看到用户 MARK 具有 CONNECT 和 LOAD 权限。要撤消这些权限,可以不选中权限旁边的复选框。
图 9. 在 Control Center 中打开修改用户(特权)对话框
![在 Control Center 中的修改用户对话框](https://i-blog.csdnimg.cn/blog_migrate/74733cf7f7ea2c43a91af7496124ee87.png)
DB2 UDB 有一个 GET AUTHORIZATIONS
命令,这是一个报告当前用户的特权的便捷命令。这个命令使用在数据库管理器配置文件和授权系统编目视图(SYSCAT.DBAUTH)中找到的值。清单 5 显示发出这个命令的结果:
清单 5. GET AUTHORIZATIONS 命令
db2 => get authorizations Administrative Authorizations for Current User Direct SYSADM authority = NO Direct SYSCTRL authority = NO Direct SYSMAINT authority = NO Direct DBADM authority = NO Direct CREATETAB authority = NO Direct BINDADD authority = NO Direct CONNECT authority = NO Direct CREATE_NOT_FENC authority = NO Direct IMPLICIT_SCHEMA authority = NO Direct LOAD authority = NO Direct QUIESCE_CONNECT authority = NO Direct CREATE_EXTERNAL_ROUTINE authority = NO Direct SYSMON authority = NO Indirect SYSADM authority = YES Indirect SYSCTRL authority = NO Indirect SYSMAINT authority = NO Indirect DBADM authority = NO Indirect CREATETAB authority = YES Indirect BINDADD authority = YES Indirect CONNECT authority = YES Indirect CREATE_NOT_FENC authority = NO Indirect IMPLICIT_SCHEMA authority = YES Indirect LOAD authority = NO Indirect QUIESCE_CONNECT authority = NO Indirect CREATE_EXTERNAL_ROUTINE authority = NO Indirect SYSMON authority = NO |
直接 权限意味着此权限是明确授予此用户的。间接 权限意味着此用户属于具有此权限的组。如果用户被明确授予了此权限,同时又属于具有此权限的组,那么他同时具有直接和间接权限。
通常,组织中的不同用户需要不同的数据库访问级别。例如,与数据库管理员相比,客户服务代表需要更受限制的访问级别。本节给出几个场景,并讨论在每个场景中需要的权限和特权。
场景 1
Tony 是财务部门的一位分析师,他每天早上运行查询,查明公司的商店的收益率。
在这个场景中,Tony 可以被授予他感兴趣的数据库上的 CONNECT 特权,以及他需要访问的所有表上的 SELECT 特权。
场景 2
Janet 是一位数据库管理员,负责公司中所有数据库的所有数据库维护活动。她的职责包括进行备份、在需要时恢复数据库、进行存储管理并运行跟踪。她应该不能访问数据库中的任何数据。
在这个场景中,Janet 可以被授予 SYSMAINT 权限。如果 SYSMAINT 太受限制了,也可以考虑授予 SYSCTRL 权限。
场景 3
Jim 是一位应用程序开发人员,他开发和测试数据库管理器应用程序。他还可以创建包含测试数据的表。
在这个场景中,Jim 需要一个或多个数据库上的 BINDADD、BIND、CONNECT 和 CREATETAB,某些特定的模式特权,以及某些表上的特权。如果他用一种外部编程语言(比如 C 或 Java)开发例程,那么可能还需要 CREATE_EXTERNAL_ROUTINE。
场景 4
Susan 是营销部门的一位规划师,她在每天晚上需要将从商店收到的新数据装载进 PRODUCT_SALES 表,从而判断新的销售趋势。
在这个场景中,Susan 需要数据库上的 CONNECT 特权、LOAD 权限以及 PRODUCT_SALES 表上的 INSERT 和 SELECT 特权。
新的 DB2 UDB 数据库管理员经常问的一个问题是,如何为用户创建适当的环境,让他们能够创建和删除自己拥有的数据库对象,同时限制其他用户访问这些对象。给每个用户提供一个他自己专用的物理数据库可以解决这个问题,但是这不是优化的解决方案。更好的解决方案可能是通过使用模式控制数据库对象访问。
模式是一种数据库对象,用于按照逻辑将相关的数据库对象分组。还常常用来表示对象所属权。模式具有相关联的特权,使模式所有者能够控制哪些用户有权在这个模式中创建、修改和删除对象。模式所有者最初具有这个模式上的所有特权,并能够将这些特权授予其他人。具有 SYSADM 或 DBADM 权限的用户可以修改用户在任何模式上拥有的特权。
在默认情况下,在创建数据库时,所有用户具有 IMPLICIT_SCHEMA 权限。这使任何用户可以在任何尚不存在的模式中创建对象。隐式创建的模式允许任何用户在其中创建其他对象。如果从 PUBLIC 撤消了 IMPLICIT_SCHEMA 权限,那么可以使用 CREATE SCHEMA 语句明确地创建模式,而且已经被隐式授予 IMPLICIT_SCHEMA 权限的用户(比如具有 DBADM 权限的用户)仍然可以隐式地创建模式。
为了让每个用户可以控制自己的数据库对象,数据库管理员可以为每个用户明确地创建一个模式。然后,管理员根据需要将模式上的特权授予单独的用户。这样就可以防止其他用户篡改在这个模式中创建的任何对象。为了进一步保护系统,还可以从 PUBLIC 撤消 IMPLICIT_SCHEMA 权限,这样的话,如果用户想创建数据库对象,那么必须通过他具有适当特权的模式来创建。这种方式使用户能够创建他们需要的数据库对象,同时避免他们篡改其他用户创建的数据库对象,或者将自己和其他人创建的对象混在一起。
在本文中,我们回顾了 DB2 UDB 中定义的各种权限级别和特权,以及如何使用命令行语法和 Control Center 将它们分配给用户。还讨论了特权的某些细节,包括隐式特权、静态和动态 SQL 之间授权方式的差异以及特权信息如何存储在系统编目表中。最后,讨论了在多用户环境中如何使用模式有效地控制对数据库对象的访问。有了这些知识,您就应该能够定义一个特权/权限策略,防止用户意外或故意地威胁系统的安全。