本篇文章是SQL Server安全系列的第五篇,详细内容请参考原文


架构本质上是一个数据库对象,其他对象的一个容器,在复杂的数据库中它能够很容易的管理各组对象。架构具有重要的安全功能。在这一篇你会学习如何给主体访问一组对象,通过给架构分配权限而不是单个表、代码模块和其他对象。你还会了解用户与架构分离的好处,以及如何提高对象安全性,如何为用户、组使用默认架构来简化对象访问管理和安全性。
Schemas with Roles and Permissions
The relationship of schemas with roles and permissions is an important security concept in SQL Server.一个完全合格的数据库对象名称由四部分组成:

server.database.schema.object

通常使用架构和对象名称来引用当前数据库下的对象。一个架构是一个对象集合,如表、代码模块,如图5.1所示。这种组织结构简化了用户管理,特别是当你需要改变对象的所有权时。但更重要的是为了安全,它简化了权限管理。

图5.1 一个包含数据库对象的示例架构
你可以将权限分配给架构应用于架构下的所有对象。例如,如果你将DogSchema架构的SELECT权限授予给一个主体,这个主体将可以查询DogSchema架构下的所有表格。和所有用户定义的数据库对象一样,架构有一个所有者可以完全控制对象。
在架构中单独设置对象权限通常是一个选项,但如果你已经将数据库中的架构设计好,在某些功能类型的数据库中,你可以在架构上设置权限,并将其应用到对象。最棒的是,你在架构上分配的权限会自动应用到你添加到架构中的任何对象。继续SELECT的例子,如果一年后你添加表DogTable4到架构DogSchema,所有对架构有SELECT权限的主体都能自动的SELECT新表。
多个用户和角色可以具有相同的默认架构,如果主体没有默认架构,SQL Server会尝试在dbo架构下查找或创建对象。
现在,你将看到如何使用架构来分配对象的权限。使用以下步骤将Purchasing架构的查询、更新、删除、插入权限授予给DataEntry用户自定义角色。在第4篇创建了DataEntry角色;如果你没有创建,请执行代码5.1

USE AdventureWorks2012;
GO
CREATE ROLE DataEntry AUTHORIZATION dbo;

代码5.1 在AdventureWorks2012数据库创建DataEntry角色
然后按照下面步骤在SSMS使用图形工具来分配所需的权限
1、对象资源管理器->数据库->AdventureWorks2012->安全性->角色->数据库角色->DataEntry
2、右击DataEntry,弹出菜单选择属性。在数据库角色属性对话框选择安全对象。如果你遵循第4篇的步骤,你应该可以看到之前为角色分配过权限的表和存储过程
3、点击“搜索”按钮打开“添加对象”对话框
4、在添加对象对话框,选择“特定类型的所有对象”选项,如图5.2所示。点击确定,打开“选择对象类型”对话框

图5.2 添加对象
5、在“选择对象类型”对话框中,向下滚动到“架构”项目,然后选择旁边的复选框。对话框应该看起来像图5.3。单击“确定”以保存选择并关闭对话框

图5.3 选择对象类型
6、返回到数据库角色属性对话框中,向下滚动安全对象列表然后点击Purchasing架构。页面的下部显示了可用的权限
7、显示页签为Purchasing架构勾选删除、插入、选择、更新授予复选框。数据库角色属性对话框如5.4所示

图5.4 设置对Purchasing架构的访问权限
到此DataEntry角色下的所有成员对AdventureWorks2012库Purchasing架构下的所有表都有选择、更新、删除和插入权限。只有当该角色的成员被拒绝任何权限时,才会出现异常。DENY阻止了他们通过角色继承的权限。
当然,你也可以使用TSQL脚本将架构上的权限授予给角色

GRANT DELETE ON SCHEMA::Purchasing TO DataEntry;
GRANT INSERT ON SCHEMA::Purchasing TO DataEntry;
GRANT SELECT ON SCHEMA::Purchasing TO DataEntry;
GRANT UPDATE ON SCHEMA::Purchasing TO DataEntry;
GO

代码5.2 给Purchasing架构授权
这些技术表明你可以创建不同的架构,在每个架构中放置不同的对象,然后在架构上分配权限。这节省了单个表上分配权限的工作。如果你授予权限给角色,正如我们对DataEntry角色的操作,你可以高效地对许多主体分配权限。这让你分割数据库,简化你的设计并实现数据库的安全性。
默认架构
在SQL-99规范定义,架构本质上是一个数据库的对象容器。它可以由一个主体拥有,如图5.5所示(同图5.1)。使用架构作为数据库对象容器的好处之一是:当Carol离开公司时,不需要改变Carol拥有的数百或数千个对象的所有权,管理员只需要改变这些架构的所有权,每个可能有成千上万的对象。这种方法是更简洁、更容易、更安全。

图5.5 Carol拥有的DogSchema架构
SQL Server允许你为用户和组分配默认的架构。设置默认架构是一种方便,并且具有一些重要的操作好处。特别是,当命名和访问对象时它消除了一些歧义。
用户默认架构
SQL Server不会自动创建具有相同名称的架构当你创建一个用户。你必须显式地创建一个架构,分配架构所有者,然后创建和添加对象到该架构。你可以(通常应该)为用户分配一个默认架构,这样所有用户创建的对象,如果没有显式地分配给另一个架构,都会成为默认架构的一部分。
本篇中的代码显示了所有的操作,当用户没有一个设置默认架构时会发生什么情况。我会解释每一步会发生什么,但你可能想独自执行代码,以更好地了解发生了什么事。当然,你自己试试吧!如果你想看看发生了什么,执行每一个代码块。
代码5.3做了演示所需的一些设置。你可能已经创建了第三篇的登录名carol,所以如果存在登录名carol首先删除它。创建DefaultSchema数据库并设置为当前数据库,接着创建登录名carol,并映射到数据库用户,并授予它创建表的权限。然后,它将执行上下文更改为用户carol。

IF suser_sid('carol') IS NOT NULL DROP LOGIN carol;
GO
CREATE DATABASE DefaultSchema;
GO
USE DefaultSchema;
GO
CREATE LOGIN carol WITH PASSWORD = 'crolPWD123%%%';
CREATE USER carol FOR LOGIN carol;
GRANT CREATE TABLE TO carol;--user EXECUTE AS LOGIN = 'carol';
GO

代码5.3 创建DefaultSchema数据库并设置carol用户
接下来的代码试图创建一个新表table1,如代码5.4所示。但之前的代码创建carol用户时并没有给它分配默认架构。SQL Server尝试使用dbo架构,这是默认的回退架构。但carol没有数据库的所有权,所以它不能在dbo架构中创建对象。

CREATE TABLE table1 (tID int);

代码5.4 尝试以carol上下文创建表
因为carol没有必要的权限,创建表语句失败并返回错误信息。
指定的架构名称 "dbo" 不存在,或者您没有使用该名称的权限。
代码5.5REVERT到原来的管理员登录,然后创建一个架构,并将架构所有者设为carol用户。你会在SQL Server中看到很多AUTHORIZATION子句,因为它可以让你在创建或更改一个对象时分配所有权。

REVERT;
CREATE SCHEMA DogSchema AUTHORIZATION carol;

代码5.5 创建DogSchema架构
再次更改执行上下文为carol,然后试图再创建表table1,但它失败了!现在的问题是,用户拥有一个架构并不意味着它是用户的默认架构。一个用户可以拥有成百上千个架构,SQL Server没有责任挑选一个作为默认架构。最终在创建表的时候显示的包含架构才能通过。代码5.6中明确地在DogSchema架构创建表

EXECUTE AS LOGIN = 'carol';
GO
CREATE TABLE DogSchema.table1 (tID int);

代码5.6 创建带有显示架构的表
如果DogSchema架构存在,第二种尝试创建表的方式,就是在创建用户的时候分配默认架构,或者后期修改用户默认架构。如代码5.7所示

CREATE USER carol FOR LOGIN carol WITH DEFAULT_SCHEMA = DogSchema;
-- or
ALTER USER carol WITH DEFAULT_SCHEMA = DogSchema;--测试可以在carol身份下执行

代码5.7 给用户carol设置默认架构
如果你执行ALTER USER语句为carol设置默认架构,然后你可以执行代码5.8成功创建表而不需指定架构。创建表的语句将创建一个DogSchema.table2表,因为DogSchema是carol的默认架构。

EXECUTE AS LOGIN = 'carol';
GO
CREATE TABLE table2 (tID int);
GO
SELECT * FROM table2;
REVERT;

代码5.8 创建表table2不需指定架构
另一个有趣的现象是,当你使用REVERT语句返回到自己的安全上下文,你不能执行代码5.9。除非你设置自己的默认架构为DogSchema,否则SQL Server将查找dbo.table2

SELECT * FROM table2;

代码5.9 在carol安全上下文之外运行会出错
你需要显式地使用架构来识别你想从中读取数据的表,如代码5.10。本代码成功,并返回DogSchema.table2中的内容。

SELECT * FROM DogSchema.table2;

代码5.10 指定架构执行SELECT语句
SQL Server用户与架构分离可以严格控制你的数据库和应用程序的安全结构。这使得它更容易管理一个数据库和SQL Server。你不需要为每一个对象设置成dbo用户所有者,这在2005之前版本很常见。
下面增加部分测试代码(原文不含)

/***使用sysadmin角色成员创建登录名caro2并映射到DefaultSchema库下的用户caro2,给用户caro2赋予创建表的权限***/
USE DefaultSchema;
GO
--step1:创建创建名、用户、分配权限
CREATE LOGIN caro2 WITH PASSWORD = 'crolPWD123%%%';
CREATE USER caro2 FOR LOGIN caro2;--默认架构为dbo
GRANT CREATE TABLE TO caro2;--user
--step2:切换到caro2上下文
EXECUTE AS LOGIN = 'caro2';
SELECT SUSER_NAME()
CREATE TABLE table11 (tID int);--指定的架构名称 "dbo" 不存在,或者您没有使用该名称的权限。
ALTER USER caro2 WITH DEFAULT_SCHEMA = DogSchema;--修改默认架构为DogSchema
CREATE TABLE table12 (tID int)--指定的架构名称 "DogSchema" 不存在,或者您没有使用该名称的权限。 --step3:授予权限
revert
grant alter on schema::DogSchema to caro2
--重新执行step2,正常
drop table table11
drop table table12
--step4:收回权限
revert
revoke alter on schema::DogSchema from caro2--恢复成刚创建时的默认权限,此时创建表失败 --step5:收回权限后再以caro2身份创建表
EXECUTE AS LOGIN = 'caro2';
SELECT SUSER_NAME()
CREATE TABLE table13 (tID int)--指定的架构名称 "DogSchema" 不存在,或者您没有使用该名称的权限。
--step6:更改架构所有者
REVERT
ALTER AUTHORIZATION ON SCHEMA::[DogSchema] TO [caro2] --重新执行step5,正常
select * from table13
drop table table13 --stpe7:测试原架构所有者
REVERT
EXECUTE AS LOGIN = 'carol';--此时carol的权限同step1仅有create table权限
SELECT SUSER_NAME()
CREATE TABLE table14 (tID int)--指定的架构名称 "DogSchema" 不存在,或者您没有使用该名称的权限。 --恢复原架构所有者,删除测试对象
REVERT
ALTER AUTHORIZATION ON SCHEMA::[DogSchema] TO [carol]
drop user caro2
drop login caro2

组默认架构
用户的默认架构,在SQL Server 2005引进,解决了查询、创建对象以及其他操作在正确的架构下使用正确的对象。但这些默认架构的存在一个问题,你可以很容易的在数据库中创建大量的架构。Windows组的默认架构,在SQL Server 2012引进,解决了这些问题。
使用下面的步骤来探索用户默认架构的潜在问题。步骤假定本地Windows有一个DBAs组,并且ClearFile用户是DBAs组中的成员。你需要更改示例代码中的机器名称。最后,DefaultSchema数据库应该已经存在。
1、修改当前数据库为DefaultSchema,代码5.11首先创建一个Windows组的登录名,然后创建DataAdmins用户映射到此登录名,接着创建DBAs角色并添加DataAdmins用户到角色中。

USE DefaultSchema
GO
CREATE LOGIN [USER-67NP5R8LGK\DBAs] FROM WINDOWS;
CREATE USER DataAdmins FROM LOGIN [USER-67NP5R8LGK\DBAs];
CREATE ROLE DBAs;
ALTER ROLE DBAs ADD MEMBER DataAdmins;

代码5.11 创建登录名、用户、角色
2、授予对DogSchema架构的创建表和控制权限给DBAs角色

GRANT CREATE TABLE TO DBAs;
GRANT CONTROL ON SCHEMA::DogSchema TO DBAs;

代码5.12 授予权限给DBAs角色
3、用ClearFile身份运行另一个SSMS。在Windows启动菜单按下SHIFT键,并且右击SSMS。在弹出的菜单中选择以其他用户身份运行,键入ClearFile的用户名和密码
4、在连接到服务器对话框使用Windows身份验证,用户名为ClearFile,如图5.6所示。点击连接,就以ClearFile身份运行SSMS

图5.6 以ClearFile身份登录SSMS
5、在刚打开的SSMS新建查询,可用数据库切换到DefaultSchema数据库
6、执行代码5.13,成功创建了表table1,但它的架构是什么呢?

CREATE TABLE table1 (tID int)

代码5.13 使用ClearFile创建表table1
7、对象资源管理器下DefaultSchema数据库展开表、用户、架构。如图5.7所示,前面语句创建的表叫USER-67NP5R8LGK\ClearFile.table1,数据库用户USER-67NP5R8LGK\ClearFile,架构USER-67NP5R8LGK\ClearFile

图5.7 没有默认架构时创建表的结果
8、回到你以管理员登录的SSMS,在对象资源管理器下按顺序删除刚才创建的表、架构和用户
9、还是在原SSMS,执行代码5.14给用户DataAdmins设置默认架构DogSchema

ALTER USER DataAdmins WITH DEFAULT_SCHEMA = DogSchema;

代码5.14 为DataAdmins用户认置默认架构
10、返回到ClearFile登录的SSMS,执行代码5.15创建新表table3。这次代码创建的表叫做DogSchema.table3,并且没有添加ClearFile数据库用户,也没有添加ClearFile架构

CREATE TABLE table3 (tID int)

代码5.15 创建表table3
你也可以在数据库用户对话框设置默认架构,如图5.8所示

图5.8 使用数据库用户对话框设置默认架构
SQL Server 2012增加了给组设定默认架构的功能,类似于给用户设定默认架构解决问题,使安全管理更容易。对于同样的原因,你创建没有任何权限的用户,然后将它们添加到需要的权限组中,你可以为组指定默认架构,而不是每个用户。与用户一样,你可以通过create user或者alter user指定默认架构。

-- Clean up
USE master;
GO
IF SUSER_SID('carol') IS NOT NULL DROP LOGIN carol;
IF SUSER_SID('caro2') IS NOT NULL DROP LOGIN caro2;
IF SUSER_SID('USER-67NP5R8LGK\DBAs') IS NOT NULL DROP LOGIN [USER-67NP5R8LGK\DBAs];
IF DB_ID('DefaultSchema') IS NOT NULL DROP DATABASE DefaultSchema;
GO

总结
架构在SQL Server管理数据库对象上是一个很好的特征,还提供了重要的安全功能。通过在一个架构上设置权限,而不是它包含的单个对象,你可以更轻松地管理数据库的权限。这是特别重要的,当你有很多主体需要授予权限时。
一定要给用户和组分配默认架构,这样就可以避免意外的对象创建,同时简化代码和数据库维护。随着对组设置默认架构的能力,微软充实了架构安全效益。

【译】第五篇 SQL Server安全架构和安全的更多相关文章

  1. 第五篇 SQL Server安全架构和安全

    本篇文章是SQL Server安全系列的第五篇,详细内容请参考原文. 架构本质上是一个数据库对象,其他对象的一个容器,在复杂的数据库中它能够很容易的管理各组对象.架构具有重要的安全功能.在这一篇你会学 ...

  2. 【译】第五篇 SQL Server代理理解代理错误日志

    本篇文章是SQL Server代理系列的第五篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.在第四篇中我们看到 ...

  3. 第五篇 SQL Server代理理解代理错误日志

    本篇文章是SQL Server代理系列的第五篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.在第四篇中我们看到 ...

  4. 【译】第九篇 SQL Server代理了解作业和安全

    本篇文章是SQL Server代理系列的第九篇,详细内容请参考原文 在这一系列的上一篇,学习了如何在SQL Server代理作业步骤启动外部程序.你可以使用过时的ActiveX系统,运行批处理命令脚本 ...

  5. 【译】第一篇 SQL Server安全概述

    本篇文章是SQL Server安全系列的第一篇,详细内容请参考原文. Relational databases are used in an amazing variety of applicatio ...

  6. 【译】第二篇 SQL Server安全验证

    本篇文章是SQL Server安全系列的第二篇,详细内容请参考原文. 验证是检验主体的过程.主体需要唯一标识,那样SQL Server可以确定主体有哪些权限.正确的验证是提供安全访问数据库对象的必要的 ...

  7. 【译】第九篇 SQL Server安全透明数据加密

    本篇文章是SQL Server安全系列的第九篇,详细内容请参考原文. Relational databases are used in an amazing variety of applicatio ...

  8. 【译】第二篇 SQL Server代理作业步骤和子系统

    本篇文章是SQL Server代理系列的第二篇,详细内容请参考原文. SQL Server代理作业由一系列的一个或多个作业步骤组成.一个作业步骤分配给一个特定的作业子系统(确定作业步骤去完成的工作). ...

  9. 【译】第一篇 SQL Server代理概述

    本篇文章是SQL Server代理系列的第一篇,详细内容请参考原文. SQL Server代理是SQL Server的作业调度和告警服务,如果使用得当,它可以大大简化DBA的工作量.SQL Serve ...

随机推荐

  1. crontab执行时间和系统时间不一致

    最近发现一个非常奇怪的问题,症状如下: crontab 定时任务 配置时间 是 10 5 * * * (每日凌晨5点10分执行) 运行脚本时间却是 18:10左右 Dec 24 05:10:01 ht ...

  2. js手风琴图片切换实现原理及函数分析

    关键词: js手风琴 js百叶窗 js百页窗 实现原理解读 使用两层for循环实现, 第一层有三个功能,分别给第个li: 添加索引 预设位置 添加事件 第二层有两个功能,整理图片位置: 鼠标的li,以 ...

  3. 修复浏览器不支持Array自带的indexOf方法的扩展

    JavaScript中Array的indexOf方法支持的浏览器有:IE9+.Firefox 2+.Safari 3+.Opera 9.5+和Chrome 如果想要在不支持的浏览器中使用indexOf ...

  4. PHP函数补完:preg_match()

    preg_match — 进行正则表达式匹配. 语法:int preg_match ( string $pattern , string $subject [, array $matches [, i ...

  5. CSS实现背景透明而背景上的文字不透明完美解决

    在我们设计制作一些网页的时候可能会用到半透明的效果,首先我们可能会想到用PNG图片处理,当然这是一个不错的办法,唯一的兼容性问题就是ie6 下的BUG,但这也不困难,加上一段js处理就行了.但假如我们 ...

  6. struts2——配置struts.xml文件

    在struts2框架中struts.xml是应当放到src的根目录,程序编译后会将struts.xml放到WEB-INF/classes目录下. Struts2在web.xml中的一般配置如下: &l ...

  7. spring boot 入门操作(三)

    spring boot入门操作 devtools热部署 pom dependencies里添加依赖 <dependency> <groupId>org.springframew ...

  8. python列表基础操作

    Python列表基本操作 记住一句话,叫做顾首不顾尾 首先我们来定义一个列表 name = ["jixuege","dajiba","boduoye& ...

  9. qsub

    1.qsub.sh for i in `ls`;do if [ -d $i ];then cd $i if [ -f *.sh ];then qsub -cwd -pe smp -q asm.q,al ...

  10. python系统编程(五)

    多线程-threading python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用 1. 使用threading模块 ...