SQL Server 2008通过将用户和schema分离开来从而解决了这个问题并实现了SQL-99 schema,如图9的下面部分所示。当你使用新的CREATE USER DDL创建一个新的用户Alice,SQL Server不再自动地创建具有相同名称的schema。相反地,你必须显式创建一个schema并将它的所有权分配给一个用户。因为显示的所有数据库对象现在包含在Schema1 schema中,这是Alice一开始拥有的,因此通过简单地更改schema的所有权给Lucinda来更改所有的schema对象的所有权就很简单了。每一个用户还可以拥有一个分配给它的默认的schema,因此SQL Server假定在默认的schema中,所有对象按名称引用而没有按schema引用。在图9的下面部分,如果Alice将Schema1作为她的默认 schema,那么她可以将这个表作为Schema1.Table1或简单地作为Table1。用户Carol可能没有一个默认的与她的用户名关联的 schema,她需要将这个表作为Schema1.Table1。任何没有定义默认schema的用户默认的schema是dbo。在SQL Server 2008中完全标准的对象名称具有一个四部分组成的结构,这与SQL Server之前版本中的类似:
SQL Server 2008安全概述(三)_休闲_02

  如同在之前版本中的一样,如果对象是在代码运行的同一台服务器上那么你可以省略服务器名称。如果连接打开了同一个数据库那么你可以忽略数据库名称。而如果它是当前用户默认的schema或者是dbo所拥有的,那么你可以忽略schema 名称,因为那是当SQL Server 试图消除一个对象名称的歧义时采取的最后手段的schema。

  使用CREATE USER 语句替代sp_adduser 来创建新的用户。这个系统存储过程仍然围绕向后的兼容性,并已被修改了一点来适应新的用户和schemas的分离。sp_adduser 创建了一个schema,它使用相同的名称作为新的用户名称或应用程序角色,并指定这个schema 作为用户默认的schema,模仿SQL Server 2000行动但提供了一个单独的schema。

  注意 在使用ALTER AUTHORIZATION 语句时,它可能会导致你拥有一个在我的中的表(反之亦然)。这会导致严重的问题。例如,谁拥有这个表上的触发器,你还是我?底线是它现在能够巧妙地发现schema范围的对象或类型的所有者。这有两个方法:

  · 使用OBJECTPROPERTY(id, 'OwnerId')来发现一个对象的真正所有者。

  · 使用TYPEPROPERTY(type,'OwnerId')来发现一个类型的真正所有者。

  SQL Server 可以使用同义字来帮助保存按键。你可以为任何使用两部分、三部分或四部分完整对象名称的对象创建一个同义字。SQL Server 使用同义字来访问定义的对象,在下面的代码中,History 同义字显示了AdventureWorks数据库中指定的schema.table。SELECT 语句返回了EmployeeDepartmentHistory表的内容。
SQL Server 2008安全概述(三)_职场_05

  你还可以为完整的四部分名称定义History 同义字,如下面的代码所示:
SQL Server 2008安全概述(三)_sql_08

  使用像这样的完整的四部分名称允许使用从另一个数据库上下文得到的同义字,假设当前的用户具有使用这个同义字和读取表的权限:
SQL Server 2008安全概述(三)_休闲_11

  还要注意,如果你不提供一个schema名称作为新的同义字名称的一部分,那它将成为默认schema 的一部分。

  5. 加密和密钥管理

  服务器级别的安全可能是系统管理员最为关注的,但是数据库是一个生产环境中所有活动发生的地方。对于大多数情况,数据库管理员可以让数据库开发人员关注于数据库的细节,只要开发人员是在环境的约束之下。SQL Server 2008提供了大量的特性用于保护数据库。

  5.1 数据加密

  SQL Server 2000 和之前的版本没有对数据库中存储的数据进行加密的内置支持。为什么你需要对安全地放置在防火墙之后的很安全的服务器上存储在很安全的数据库中的数据进行加密?这是因为有一个出现了几年的重要的安全原则——defense in depth。Defense in depth意味着分层防范,以便即使攻击者突破了你最外层的防御,他们还是需要再通过层层防御才能抵达中心。在一个数据库中,这意味着如果一个攻击者通过了防火墙和服务器上的Windows安全后抵达了数据库,她还是需要作些工作来试图解析你的数据。而且,在数据和隐私受到法律保护的今天,数据需要进行强有力的保护。

  SQL Server 2008使用对称和非对称密钥以及数字证书提供了对广泛的数据加密种类的大力支持。最重要的是,它为你管理密钥,因为到目前为止,密钥管理是最难加密的部分。保密秘密绝非易事。

  作为一个管理员,你可能至少要管理密钥层级的上层,如图10所示。数据库管理员需要了解服务器级别的服务主密钥和数据库级别的数据库主密钥。每一个密钥保护它的子密钥,而这些子密钥反过来保护它们自己的子密钥,这样在树型结构中传递下去。一个例外就是当一个密码是保护一个同义字密钥或证书的时候,这是SQL Server 让用户管理他们自己的密钥和保证密钥的隐密性的方式。
SQL Server 2008安全概述(三)_sql_14

  注意 Microsoft建议不要直接使用证书或非对称密钥来加密数据。非对称密钥加密会将性能降低很多倍,而且你使用这个机制所能保护的数据量是受限的,它取决于密钥模块。你可以使用一个密码而不是数据库主密钥来保护证书和非对称密钥。

  服务主密钥是一个管理SQL Server 中所有密钥和证书的密钥。它是SQL Server在安装过程中自动创建的一个同义字密钥。它显然是一个重要的秘密,因为它被知道了的话,那么攻击者就可以解析SQL Server管理的服务器上的每一个密钥。Windows中的数据保护API(Data Protection API ,DPAPI)会保护服务主密钥。

  SQL Server为你管理服务主密钥,不过你可以在它上面执行维护任务将它输入到一个文件中,重新生成它,并从一个文件将它恢复回来。然而,大多数情况下你不需要或不想要对密钥做任何修改。对于管理员来说,最好备份他们的服务主密钥,以防密钥崩溃。

  在数据库范围内,数据库主密钥是所有密钥、证书和数据库中的数据的根加密对象。每一个数据库可以有一个单独的主密钥;你如果试图创建第二个密钥那你会得到一个错误信息。你必须使用CREATE MASTER KEY Transact-SQL以用户提供的密码来创建一个数据库主密钥:   
  CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'EOhnDGS6!7JKv'

  SQL Server 使用从密码和服务主密钥获得的一个三重数据加密标准密钥来加密密钥。第一个拷贝存储在数据库中,第二个拷贝存储在主数据库中。让数据库主密钥由服务主密钥来保护,这使得当需要的时候SQL Server可以自动地解密数据库主密钥。终端应用程序或用户不必使用密码打开主密钥,而且这是将密钥保护于层次之中的一个主要的好处。

  分离数据库和一个现有的主密钥,并将它移到另一个服务器上,这是一个棘手的事。问题在于新的服务器的服务主密钥和其它的服务器的服务主密钥是不同的。因此,服务器不能自动地解析数据库主密钥。通过使用加密所采用的密码来打开数据库主密钥并使用ALTER MASTER KEY 语句和新的服务主密钥将它加密,这样可以解决这个问题。否则,你总是需要在使用前打开数据库主密钥。

  一旦有了数据库主密钥,开发人员就可以使用它来创建三种密钥类型中的任何一个,这取决于所要求的加密类型:

  · 非对称密钥,用于具有一个公共密钥和一个私人密钥对的公共密码匙

  · 对称密钥,用于使用相同的密钥进行加密和解密数据的共享秘密的情况下

  · 证书,实质上是一个公共密钥的封装

  有了这所有的加密选项以及它和服务器以及数据库的深入集成,现在加密已经是一个为你的数据添加最后一道防线的可行方法。但是,要明智地使用这个工具,因为加密会对你的服务器增加许多处理消耗。

  透明的数据加密

  在SQL Server 2005中,你可以通过编写使用数据库引擎的加密功能的定制Transact-SQL来加密数据库中的数据。SQL Server 2008在这基础上推出了透明数据加密。

  透明数据加密执行所有的数据库级别的加密操作,这消除了应用程序开发人员创建定制的代码来加密和解密数据的要求。数据在写到磁盘时进行加密,从磁盘读的时候解密。通过使用SQL Server来透明地管理加密和解密,你可以保护数据库中的业务数据而不必对现有的应用程序做任何修改,如图11所示。
SQL Server 2008安全概述(三)_职场_17

  数据库加密密钥(DEK)是用来执行加密和解密的,这个DEK存储在数据库启动记录中,在恢复场景中可用。你可以使用服务主密钥或硬件安全模块(HSM)来保护这个DEK。HSM通常是USB设备或智能卡,因此不容易被偷或丢失。

  5.2 可扩展的密钥管理

  随着调整遵从性和对数据保密性的整个关注的不断发展,越来越多的公司使用加密作为一种提供深度防范的解决方案。随着公司使用越来越多的加密和密钥来保护他们的数据,密钥管理变得越来越复杂。一些高安全性的数据库使用上千个密钥,而你必须使用一个系统来存储、释放或重建这些密钥。更进一步的,你应该将这些密钥与数据分开存储,以提高安全性。

  SQL Server 2008推出了供第三方供应商使用的加密功能。这些解决方案与SQL Server 2005 和SQL Server 2008数据库无缝地合作使用,提供了企业级的专一的密钥管理。这将密钥管理工作从SQL Server移到了专一的密钥管理系统。

  SQL Server 2008中的可扩展的密钥管理还支持HSM的使用,从而提供了密钥和数据物理上的分离。

  5.3 代码模块签名

  在SQL Server 中进行加密的一个好处是它提供了使用证书数字化签名代码模块的功能(存储过程、函数、触发器和事件通知)。这提供了对数据库表和其它对象的访问的更细粒度的控制。像加密数据一样,你使用证书中所包含的私钥来签名代码。结果在签名的代码模块中使用的表只能通过代码来访问,而不允许从代码模块的外部访问到。换句话说,只有使用用来签名这个模块的证书才能访问到这些表。

  对于存储过程情况是一样的。例如,如果它有一个没有被破坏的所有权链,你谨慎地控制哪些用户具有对这个存储过程的EXECUTE 权限,而且你直接拒绝对后台的表的访问。但是这在一些情况下不起作用,例如当这个存储过程的所有权链被破坏了或者执行动态的SQL,要求这个用户执行存储过程具有对后台的表的权限。要实现同样目的的另一个方法是使用EXECUTE AS ,但是这会改变存储过程执行环境的安全上下文。这可能是不希望的,例如,如果你需要在表中记录哪个用户使得这个存储过程运行(需要记录作为这个存储过程参数的用户名称)。

  签名代码模块还具有保护证书免于对代码模块的未授权的改动的好处。像其它数字签名的文档一样,当代码改变时证书就无效了。代码不在证书的上下文下执行,所以任何具有对该证书的访问权限的对象将不能被访问到。

  为了做到这一点,你可以创建一个证书,将它和一个新的用户关联起来,并使用这个证书来签名这个存储过程。为这个用户授权所有执行这个存储过程所必要的权限。实际上,你将这个用户添加到了这个存储过程的安全上下文中作为第二标识。然后将执行权限授予所有需要执行这个存储过程的用户和角色。下面的代码显示了这些步骤。假设你想签名mySchema.GetSecretStuff 存储过程,而所有引用的对象都已经存在于数据库中了:
SQL Server 2008安全概述(三)_数据库_20

  现在只有明确地被授予在存储过程上的EXECUTE权限的用户可以访问这个表的数据。

  6. SQL Server 2008中的审查

  任何安全解决方案的一个重要部分是具有审查责任和调整遵从性原因的活动的能力。SQL Server 2008具有一些使它可以审查活动的特性。

  6.1 所有活动审查

  SQL Server 2008具有通过审查对象对审查的支持,这使得管理员可以捕捉数据库服务器中的活动并将它存储在日志中。有了SQL Server 2008,你可以将审查信息存储在以下目的地中:

  · 文件

  · Windows应用程序日志

  · Windows安全日志

  为了写到Windows安全日志中去,SQL Server 安全必须被配置为作为本地系统、本地服务、网络服务或一个具有SeAuditPrivilege权限但不是交互的用户的域帐户来运行。

  为了创建一个审查对象,你必须使用CREATE SERVER AUDIT语句。这个语句定义了一个审查对象,并将它与一个目的地相关联。这个特定的选项习惯于配置一个依赖于审查目的地的审查对象。例如,下面的 Transact-SQL代码创建了两个审查对象;一个记录活动到一个文件中,另一个记录活动到Windows应用程序日志中:
SQL Server 2008安全概述(三)_休闲_23

  注意在记录到一个文件目的地中时,文件名称没有在CREATE SERVER AUDIT语句中指定。审查文件名称采用AuditName_AuditGUID_nn_TS.sqlaudit 的形式,其中AuditName 是审查对象的名称,AuditGUID是与审查对象关联的唯一标识符,nn是用于分割文件组的分区编码,而TS是一个timestamp类型的值。例如,通过之前的代码示例创建了HIPAA_FILE_Audit审查对象,它可以产生一个日志文件,其名称与下面的类似:

  HIPAA_File_Audit_{95A481F8-DEF3-40ad-B3C6-126B68257223}_00_29384.sqlaudit

  你可以使用QUEUE_DELAY 审查选项为性能原因执行异步的审查,而ON_FAILURE选项决定当审查信息不能写到目的地时所要采取的行动。在之前的 HIPAA_AppLog_Audit示例中所显示的,ON_FAILURE选项配置为当日志不能写的时候关闭SQL Server示例;在这种情况下,执行CREATE SERVER AUDIT语句的用户必须具有SHUTDOWN权限。

  在你创建了一个审查对象时,你可以使用CREATE SERVER AUDIT SPECIFICATION和CREATE DATABASE AUDIT SPECIFICATION语句为它添加事件。CREATE SERVER AUDIT SPECIFICATION 添加服务器级别的行动组(在服务器级别会发生的相关行动的预定义集合)到一个审查中去。例如,下面的代码添加了FAILED_LOGIN_GROUP 行动组(它记录了失败的登陆尝试)到HIPAA_File_Audit审查中去。
SQL Server 2008安全概述(三)_sql_26

  CREATE DATABASE AUDIT SPECIFICATION语句添加数据库级别的行动组和将单个的数据库事件添加到一个审查中去。添加单独的行动使得你可以过滤基于这个活动涉及的对象和用户来记录的行动。例如,下面的代码示例添加了DATABASE_OBJECT_CHANGE_GROUP行动组(它记录数据库中的任何CREATE、 ALTER或DROP操作)和将用户SalesUser或 SalesAdmin在Sales schema中对对象执行的任何INSERT, UPDATE, or DELETE语句添加到HIPAA_AppLog_Audit审查中去。
SQL Server 2008安全概述(三)_数据库_29

  审查对象提供了一个可管理的审查框架,它使得定义应该被记录的事件和日志应该存储的位置变得很容易。这个对SQL Server 的补充帮助你执行一个完全的审查解决方案来保护你的数据库和满足调整遵从性要求。

  6.2 DDL触发器

  DDL触发器是在SQL Server 2005中推出的,不像表中的数据改变时所执行的Transact-SQL代码的DML触发器,一个DDL触发器是在表的结构改变时才触发。这是一个很好的跟踪和审查对数据库schema的结构化改变的方法。

  这些触发器的句法类似于DML触发器的语法。DDL触发器是AFTER 触发器,它对DDL语言事件作出响应;它们不对执行DDL等的类似操作的系统存储过程作出响应。它们完全是事务型的,所以你可以回滚一个DDL操作。你可以在一个DDL触发器中运行Transact-SQL或CLR 代码。DDL触发器还类似于其它的模块一样支持EXECUTE AS 条件语句。

  SQL Server 提供了关于触发器事件作为非强类型的XML的信息。它可以通过一个叫做EVENTDATA()的新的输出XML的内置功能来实现。你可以使用XQuery 表达式来解析EVENTDATA() XML ,以便能够发现像schema名称、目标对象名称、用户名称还有触发触发器的整个Transact-SQL DDL语句等的事件属性。

  数据库级别的DDL触发器触发于数据库级别和之下的DDL语言事件。例如CREATE_TABLE、ALTER_USER 等等。服务器级别的DDL触发器触发于服务器级别的DDL语言事件,例如CREATE_DATABASE、ALTER_LOGIN等等。为了管理方便,你可以使用事件组,像DDL_TABLE_EVENTS作为所有CREATE_TABLE、ALTER_TABLE和DROP_TABLE事件的总的简称。这些广泛的DDL事件组和事件类型,以及它们所关联的XML EVENTDATA(),在SQL Server 在线书籍中有描述。

  和DML触发器的名称不一样,DML触发器的名称是schema 范围的,而DDL触发器名称是数据库范围的或服务器范围的。

  使用这个新的目录视图来找出用于DML触发器和数据库级别的DDL触发器的触发器元数据:
SQL Server 2008安全概述(三)_职场_32

  如果parent_class_desc 字段具有一个‘DATABASE’值,那么它是一个DDL触发器,并且名称是数据库本身范围内的。Transact-SQL 触发器的代码体在sys.sql_modules 目录视图中可以看到,你可以将它连接到sys.triggers 的object_id 字段上。关于一个CLR触发器的元数据可以在sys.assembly_modules 目录视图中看到,你可以将它连接到sys.triggers的object_id字段上。

  使用目录视图来找出服务器范围的DDL触发器的元数据:
SQL Server 2008安全概述(三)_休闲_35

  Transact-SQL 服务器级别的触发器的代码体可以在sys.server_sql_modules 目录视图中看到,你可以将它连接到sys.server_triggers的object_id字段上。关于一个CLR服务器级别的触发器的元数据可以在 sys.server_assembly_modules目录视图中找到,你可以将它连接到sys.server_triggers的object_id 字段上。

  你可以使用DDL触发器来捕捉和审查数据库中的DDL活动。创建一个具有非强类型的XML字段的审查表。为DDL事件或你感兴趣的事件组创建一个EXECUTE AS SELF DDL 触发器。这个DDL触发器的代码体可以简单地将EVENTDATA() XML插入到审查表中。

  DDL触发器的另一个有趣的使用是触发于CREATE_USER 事件然后添加代码到自动权限管理中去。例如,假设你想让所有的数据库用户获得一个对存储过程P1、P2和P3的GRANT EXECUTE 权限。DDL触发器可以从EVENTDATA() XML中提取用户名称,动态地生成一个语句,像‘GRANT EXECUTE ON P1 TO someuser’,然后对它EXEC()。

  7. 总结

  SQL Server 2008提供了丰富的安全特性来保护数据和网络资源。它能够更容易地安全安装,因为除了最根本的特性之外,其它的都不是默认安装的或者是它们安装了但是是没有打开的。SQL Server提供了丰富的工具来配置服务器,特别是SQL Server Surface Area Configuration Tool,它的验证特性更强了,因为SQL Server与Windows验证更紧密地集成在一起,并保护脆弱的或是久远的密码。授予和控制一个用户通过验证之后可以做什么具有了更细粒度的权限、 SQL Server Agent代理和执行上下文,从而变得更加灵活了。甚至是元数据都更加安全了,因为系统元数据视图只返回了关于该用户在某种形式下具有对其的权限的对象的信息。在数据库级别,当用户和schemas的分离使得管理用户变得更加容易的同时,加密提供了最后的一道安全防线。