要求:在特定模式中创建表的用户应该拥有该表,有权访问该模式的其他用户不应该能够对该表执行任何操作(包括读取)。
示例:
此要求预计适用于有权访问“schema1”的用户,因此他们创建的表只能由他们访问,而不能由其他用户访问。
为了讨论方便,让我们创建新的登录名、新的架构和新的用户。
use master
GO
CREATE LOGIN SO_Login WITH PASSWORD = 'Dont1Use2This3In4Production'
GO
Use AdventureWorks2019
GO
CREATE SCHEMA SO_Schema
GO
CREATE USER SO_User FOR LOGIN SO_Login;
GO
理论上,您只需制定一条允许在特定模式上创建表的规则即可获得您正在寻找的内容。比如:
GRANT CREATE TABLE ON SCHEMA::SO_Schema TO public;
在这种情况下,我们可以为每个人提供在架构上创建表的选项,并在创建表上使用简单的 DDL 触发器,以便为创建表的用户添加 SELECT、DELETE、INSERT、UPDATE 等权限。
不幸的是,不支持 GRANT CREATE TABLE ON SCHEMA。
要创建表,您需要在数据库中拥有 CREATE TABLE 权限,并对正在创建表的 SCHEMA 拥有 ALTER 权限。
这使得任务更加复杂,在大多数情况下可能不推荐,因为您需要提供比您真正希望用户拥有的权限更多的权限...
如果您仍然想完成这项工作(违反建议),那么您将需要 GRANT ALTER ON SCHEMA 和 GRANT CREATE TABLE on database 给所有人 - 全部意味着“公共”
use AdventureWorks2019
GO
GRANT ALTER ON SCHEMA::SO_Schema TO public;
GO
GRANT CREATE TABLE TO public;
GO
接下来,您需要拒绝不寻常的权限,因为上述内容将赋予所有用户比您想要的更多的权力!
这可以通过在数据库上为任何 DDL_DATABASE_LEVEL_EVENTS 创建 DDL 触发器来完成
在触发器内,您应该检查发生了什么事件。如果它不是 CREATE_SCHEMA 或执行该事件的用户不应该 CREATE SCHEMA 那么你
ROLLBACK TRANSACTION;
。
注意! 由于您不希望每次新用户需要创建表并将用户名添加到可以创建表的用户硬编码列表时更改触发器,因此最好创建新角色并简单地添加您需要此角色的每个用户
CREATE ROLE ModifyTable;
GO
在这种情况下,您基于像上面这样的角色
ModifyTable
,您可以仅将 GRANT ALTER ON SCHEMA 和 GRANT CREATE TABLE 授予 ROLE ModifyTable,而不是授予 public
此外,在同一个触发器中,如果用户是应该能够创建表的用户之一,那么您应该授予他对他刚刚创建的表进行 INSERT、DELETE、UPDATE、SELECT 的权限。
请记住,如果您忘记拒绝该用户或其他所有用户的权限,那么您可能会遇到安全问题 - 这就是为什么不推荐这样做的原因。
您最好的选择是重新设计系统,这样您就不需要这种精确的招聘。所以...您可以按照我在这里解释的那样进行操作,但在大多数情况下不建议这样做。
更好的方法是不允许用户创建表,除非您可以信任所有表。您应该直接或使用您控制的应用程序为您的用户创建表,并授予他们使用他们需要的特定表的权限。不建议将 ALTER SCHEMA 权限授予简单用户!
对架构具有 ALTER 权限的用户可以创建架构所有者拥有的过程、同义词和视图。这些对象将可以(通过所有权链接)访问模式所有者拥有的其他模式中的信息。如果可能,如果模式的所有者还拥有其他模式,您应该避免授予对该模式的 ALTER 权限。