SQL Server安全(5/11):架构与安全(Schemas and Security)
在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切。但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念。这篇文章提供了基础,因此你可以对SQL Server里的安全功能充分利用,不用在面对特定威胁,不能保护你数据的功能上浪费时间。
架构本质上是另一个数据库对象,对于其它对象的容器,让在复杂的数据库里管理对象组更加容易。但架构也有重要的安全功能。在这篇文章里你会学到你如何给主体访问一组对象,通过在架构上分配许可,而不是各个表、代码模块(存储过程)和其它对象。你也会学到用户架构的好处,它如何提高对象安全性,如何为用户和组使用默认架构简化对象访问管理和安全。
有角色和许可的架构
在SQL Sever里,架构与角色和许可的关系是个重要的安全概念。完整的数据库对象名称包含四个部分:
服务器名称.数据库名称.架构名称.对象名称(server.database.schema.object)
通常你需要使用架构和对象名称来引用在当前数据库上下文的对象。架构是对象的集合,例如表和代码模块,如插图5.1所示。这个组织结构简化了用户管理,尤其当你需要修改对象的所有者。但对安全更加重要,它简化了许可管理。
插图5.1:包含数据库对象和用户所拥有的架构样本
你可以在架构上分配许可应用到架构里的所有对象。例如,如果你在DogScheme分配SELECT许可给一个主体,在那个架构里的所有表都会有那个许可。像所有用户自定义数据库对象,架构有一个所有者,可以在对象上完全控制。
在架构里对象上各自设置许可也是可以的,但是你如果在数据库里也设计了架构, 在某种功能类别里,对于数据库更有意义,你可以在架构上设置许可应用到几十个甚至上百的对象。最大的好处,在架构上分配的许可会自动应用到以后添加到这个架构的对象。继续SELECT例子,如果1年后你添加DogTable4到DogScheme,在架构上有SELECT许可的所有主体会自动有在新表的SELECT许可。
多个用户或角色可以有同样的默认架构,如果一个主体没有设置默认架构,SQL Sever会在dbo架构里寻找或创建对象。
现在你会看到你如何使用架构分配许可到对象。使用下列步骤在Purchasing架构上授予SELECT,UPDATE,DELETE和INSERT许可到AdventureWorks2012数据库里的DataEntry用户自定义数据库角色。这个角色是在第4篇里创建的;如果你没有创建,在SSMS里执行下列代码:
1 USE AdventureWorks2012; 2 GO 3 CREATE ROLE DataEntry AUTHORIZATION dbo;
代码5.1:在AdventureWorks2012数据库里创建DataEntry角色。
下列这些步骤在SSMS里使用图形工具来分配需要的许可。
- 对于AdventureWorks2012数据库在对象浏览器里展开【安全性】节点。依次展开【角色】【数据库角色】【DataEntry】。
- 右击【DataEntry】角色从弹出的菜单里选择【属性】。在【数据库角色属性】对话框里选择【安全对象】页。
如果你按着第4篇的步骤,你应该可以看到那时对这个角色分配的表和存储过程许可。 - 点击【搜索】按钮打开【添加对象】对话框。
- 在【添加对象】对话框里,选择【特定类型的所有对象】选项,如插图5.2所示,点击【确定】打开【选择对象类型】对话框。
插图5.2:选择【特定类型的所有对象】 - 在【选择对象类型】对话框里,向下滑动到【架构】项目并选择前面的复选框。对话框应该如插图5.3所示。点击【确定】保存选择,关闭对话框。
插图5.3:选择【架构】对象类型 - 回到【数据库角色属性】对话框,在页面的上部向下滑动安全对象列表,点击Purchasing架构。在页面的下部会显示可用许可。
- 对于表单的Purchasing部分,在【显式】分页上许可里的【授予】列选择插入、更新、删除、选择许可。【数据库角色属性】对话框如插图5.4所示。
插图5.4:为Purchasing架构设置表访问许可 - 点击【确定】提交修改。
现在DataEntry角色的所有成员在AdventureWorks2012数据库的Purchasing架构的表上有SELECT,UPDATE,DELETE和INSERT许可。只有当角色里的各个成员拒绝了任何许可才会报错。这阻止了它们在角色里通过成员资格继承的拒绝许可。
或者,你也可以使用代码5.2来授予架构这些许可。
1 GRANT DELETE ON SCHEMA::Purchasing TO DataEntry; 2 GRANT INSERT ON SCHEMA::Purchasing TO DataEntry; 3 GRANT SELECT ON SCHEMA::Purchasing TO DataEntry; 4 GRANT UPDATE ON SCHEMA::Purchasing TO DataEntry; 5 GO
代码5.2:添加DELETE,INSERT,SELECT和UPDATE许可到Purchasing架构的代码。
这些技术展示了你可以创建不同的架构,在每个架构里放入不同的对象,然后在架构上分配许可。这个节约了在各个表上分配许可的所有工作。如果你分配许可到角色,这里我们可以使用DataEntry角色,你可以高效分配许可到许多许可——角色里的所有成员——一次搞定。这让你划分你的数据库,像在AdventureWorks2012里按部门来实现一样,简化你任何设计和实现数据库安全。
默认架构
如SQL-99规范所定义的,架构本质上是数据库里对象的容器。然后它可能依次属于一个主体,如插图5.5所示。使用架构作为数据库对象的容器的一个好处,当Woodytu离开公司,管理员不用修改Woodytu拥有的成百上千个对象的所有者,只要修改这些架构的所有者,每个架构都会上上千个对象。这个方法更加简洁,更加容易,也更安全。
插图5.5:Woodytu拥有TreeSchema架构
SQL Server让你为用户和组分配默认架构。设置默认架构的能力既方便又有一些业务上的重要好处。实际上,当命名和访问对象的时候,它移除了这些分歧。
用户默认架构
当你创建一个用户时,SQL Server不会自动创建和用户一样名字的架构名。而是你需要创建一个架构,分配成员资格给用户,然后创建和添加对象给架构。你可以(通常应该)分配一个默认架构给用户,这样的话用户创建的所有对象——不会分配给另一个架构——变为默认架构的一部分。
这篇文章的代码展示这一切如何发生的,会展示当用户默认架构时会发生什么。这里我会解释每一步发生了什么,但你最好和我一起做,这样可以更清楚看到发生了什么。
代码5.3为演示做一些需要的配置。你可能在第3篇里创建了carol登录,因此如果存在的话代码首先删除,开始使用不同的许可。创建DefaultSchema数据库后,修改数据库上下文为它,代码创建了carol登录,在数据库里映射它到登录carol,并授予它创建数据库的能力。然后运行上下文到新的用户carol。
1 IF suser_sid('carol') IS NOT NULL DROP LOGIN carol; 2 GO 3 CREATE DATABASE DefaultSchema; 4 GO 5 USE DefaultSchema; 6 GO 7 8 CREATE LOGIN carol WITH PASSWORD = 'crolPWD123%%%'; 9 10 CREATE USER carol FOR LOGIN carol; 11 GRANT CREATE TABLE TO carol; 12 13 EXECUTE AS LOGIN = 'carol'; 14 GO
代码5.5:创建DefaultSchema数据库并设置用户carol的代码
提示:
在第6篇里你会学到更多执行上下文和EXECUTE AS语句。现在,你只要知道这个功能提供一种使用安全上下文(用户和你指定的登录捆绑的许可)执行语句的方法。因此在代码5.3当你执行EXECUTE AS语句后,接下来的语句会以carol的许可执行,直到你用REVERT语句撤销回你自己的许可。
下面的代码5.4会创建新的table1表。但当刚才的代码创建carol时没有分配默认架构。SQL Server尝试使用dbo架构,这是默认后退的架构。但Carol在数据库里没有成员资格权限,因此她不能在dbo架构里创建对象。
1 CREATE TABLE table1 (tID int);
代码5.4:在carol运行上下文里阐释创建table1表
因为carol没有需要的CREATE TABLE语句许可,这个执行会失败,会有如下的错误信息。
消息 2760,级别 16,状态 1,第 1 行
指定的架构名称 "dbo" 不存在,或者您没有使用该名称的权限。
代码5.5返回原先开始会话的管理员登录,然后创建一个架构并把成员资格给用户carol。在SQL Server里你会看到很多AUTHORIZATION字句,因为它让你在同样的创建或修改对象的语句里分配成员资格。
1 REVERT; 2 CREATE SCHEMA DogSchema AUTHORIZATION carol;
代码5.5:创建属于carol的DogSchema架构的代码
然后代码再次修改执行上下文为carol,再次尝试创建table1。但又一次失败了。
1 CREATE TABLE table1 (tID int);
现在的问题是用户拥有的架构并不意味着它是用户的默认架构。用户可以拥有上百个架构,但SQL Server不会拿个作为默认。但最后在架构里创建表会怎样。代码5.6里的语句会在DogSchema架构里创建table1,最后它成功了。
1 CREATE TABLE DogSchema.table1 (tID int);
代码5.6:创建指定架构的表。
成功执行!
第二次尝试创建表,一旦DogSchema存在,会成功执行。因此代码要在首次创建用户时分配默认架构,或者稍后修改它,如代码5.7所示。
1 CREATE USER carol FOR LOGIN carol WITH DEFAULT_SCHEMA = DogSchema; 2 -- or 3 ALTER USER carol WITH DEFAULT_SCHEMA = DogSchema;
代码5.7:在创建用户时,为carol设置默认架构或稍后修改它的代码
如果你运行ALTER USER语句为carol设置默认架构,那么你可以成功执行代码5.8,不需要指定架构来创建table2表。CREATE TABLE语句会创建DogSchema.table2表。因为DogSchema是carol的默认架构,是SQL Server使用的架构。
1 EXECUTE AS LOGIN = 'carol'; 2 GO 3 CREATE TABLE table2 (tID int); 4 GO 5 SELECT * FROM table2; 6 REVERT;
代码5.8:在设置carol的默认架构后,不指定架构创建table2表。
另一个有趣的事是,在撤回你自己的安全上下文后——使用REVERT语句——你不能运行代码5.9。除非你设置你的默认架构是DogSchema,SQL会查找dbo.table2表,它不存在。
1 SELECT * FROM table2;
代码5.9:当不在carol的执行上下文里运行时,这个代码会引起错误
正确的做法,你需要使用架构来标识你想要读取的数据的表来源,如代码5.10所示。这个代码会成功,并返回DogSchema.table2的内容(现在还是空的)。
1 SELECT * FROM DogSchema.table2;
代码5.10:当用户默认架构不是DogSchema时进行SELECT操作
在SQL Server里用户和架构的分离还是你能保持你对你的数据库和应用程序的安全架构的完全控制。它让管理数据库和SQL Server更加简单。你不应该让dbo拥有一切,这在SQL Server 2005之前常见的做法。
组默认架构
SQL Server 2005里引入的针对用户的默认架构,解决了层级确定性问题,在查询,创建对象和其它操作时要在正确的架构里使用正确的对象。但这些默认架构的对应的副作用是你很容易会在数据库里留下很多隐式创建的架构。在SQL Server 2012里引入的针对Windows组的默认架构,解决了这些问题。
按照步骤来探寻只针对用户的默认架构的潜在问题。这些步骤假定你的Windows本地实例里有名为DBAs的组和Woodytu的登录是这个组的成员。在代码里你也要修改WIN10为你的本地机器名称。最后,DefaultSchema数据库应该已经存在;如果没有的话可以参考前面的代码来创建。
你可以按下列步骤来练习。具体步骤有点微妙,因为你会在2个SSMS实例里练习。把每个代码段当做一个整体进行执行。
- 修改数据库上下文为DefaultSchema后,执行代码5.11。它创建一个映射到Windows里DBAs组的登录和一个用户映射到这个登录,然后创建DBAs角色添加DataAdmins用户到它里。
1 CREATE LOGIN [Win10\DBAs] FROM WINDOWS; 2 CREATE USER DataAdmins FROM LOGIN [Win10\DBAs]; 3 CREATE ROLE DBAs; 4 ALTER ROLE DBAs ADD MEMBER DataAdmins;
- 接下来的代码5.12,在DogSchema架构上授予CREATE TABLE和CONTROL许可给DBAs角色。
1 GRANT CREATE TABLE TO DBAs; 2 GRANT CONTROL ON SCHEMA::DogSchema TO DBAs;
代码5.12:授予许可给DBAs角色
- 现在打开SSMS的另一个实例以woodytu用户登录(woodytu隶属于DBAs组)。按住SHIFT键,在开始菜单里右击SSMS。从弹出的菜单里选择【以其它身份用户运行】, 弹出的对话框里输入woodytu的凭证。
- 在SSMS里连接到服务器的对话框,使用Windows身份验证,以woodytu登录,如插图5.6所示。点击【连接】,现在你以woodytu运行SSMS.
插图5.6:以woodytu登录到SQL Server - 切换数据库上下文为DefaultSchema。
- 执行下列代码5.13,这会成功创建table1表,但它的架构是什么呢?
1 CREATE TABLE table1 (tID int)
代码5.13:以woodytu执行CREATE TABLE语句
- 在对象浏览器里DefaultSchema数据库里,展开【表】、【安全性】下的【用户】和【架构】三个节点。如插图5.7所示,CREATE TABLE语句创建了WIN10\woodytu.table1的表,WIN10\woodytu的数据库用户。在架构里创建一个表带来太多的碎片,不是我们想要的。
插图7:没有使用默认架构创建一个表的结果 - 返回刚才的SSMS实例,以管理员登录的那个。从对象浏览器里删除刚才说的表,架构和用户,按这个顺序。
- 还是刚才的SSMS实例,运行代码5.14来为DataAdmins用户设置默认架构,使用刚才创建的DogSchema。
1 ALTER USER DataAdmins WITH DEFAULT_SCHEMA = DogSchema;
代码5.14:为DataAdmins角色设置默认架构的代码
- 再次回到woodytu的SSMS实例,运行代码5.15来再次创建一个新表。这次这个代码创建名为DogSchema.table3,woodytu不会用自己的名称创建一个用户和架构。
1 CREATE TABLE table3 (tID int)
代码5.15:创建table3,现在DogSchema架构里。
你也可以在【安全性】【用户】里的DataAdmins的【属性】里,打开的【数据库用户】对话框里设置用户的默认架构,如插图5.8所示。
插图5.8: 使用数据库用户对话框设置用户的默认架构。
SQL Server 2012添加可以为组和用户定义默认架构的能力,这在解决默认架构问题提供了很大的帮助,让管理也更加简单。同样的原因,你创建没有许可的用户,添加它们到有它们需要许可的组里,你可以为组指定默认的架构来应用到它的成员,而不是为每个用户。你可以使用CREATE USER或ALTER USER语句为组指定默认的架构。
小结
架构是SQL Server一个很好的功能,把数据库对象放入方便的容器里进行管理,它也提供了重要的安全功能。通过在架构上设置许可而不是它包含的对象,你可以更容易管理数据库架构许可。当你有大量需要授予许可的主体时,这个尤为重要。
一定要永远为用户和组同时分配架构,这样的话你可以避免不必要的对象创建,并同时简化代码和数据库维护。有了可以为组设置默认架构的能力,微软因安全充实架构的益处。
原文链接:
注:此文章为WoodyTu学习MS SQL技术,收集整理相关文档撰写,欢迎转载,请在文章页面明显位置给出此文链接!
若您觉得这篇文章还不错请点击下右下角的推荐,有了您的支持才能激发作者更大的写作热情,非常感谢!