22.2 安全性选项
就内置选项来说,关于如何在SQL Server中设置安全性的问题,你有两个选择。
l Windows集成安全性——用户登录到Windows中而非SQL Server中。身份验证是通过Windows以可信的连接来完成的。
l 标准的安全性——与登录到Windows中分离开,用户单独登录到SQL Server中。身份验证是使用SQL Server来完成的。
我们来看看这两种选择。
22.2.1 SQL Server安全性
先从SQL Server的内置登录模式谈起。在SQL Server 2005中,这方面变得更加健壮。尽管依然可以使用相对简单的模式,但是,现在你可以做大量其他的事情,以便增加服务器和数据库的安全。
在使用SQL Server安全性时,是完全脱离开网络登录信息来创建登录ID的。使用SQL Server安全性的有利之处包括:
l 用户不必为了访问到系统而成为域用户;
l 更容易对用户信息进行程序化的控制。
一些不利之处是:
l 用户可能必须登录两次或者更多次——一次是登录到他们拥有访问权的网络中,而一次是针对用户从单独的应用程序所创建的每一个连接,登录到SQL Server中;
l 两次登录意味着DBA要做更多的维护;
l 如果需要多个密码,则它们很容易变得不一致,这会导致大量的登录失败和密码遗忘。(这听上去耳熟吗,“现在我们来看看,哪一个密码才是用于这个登录的?”)
用SQL Server安全性进行登录的一个例子是使用sa账户的情形,在本书的大部分地方可能都会使用该账户。使用SQL Server安全性进行登录时,你是如何登录到网络中的并不重要,可以使用sa登录ID和单独的密码登录到SQL Server中(希望该密码设置得非常安全)。
实际上,从经常性看,你不会日复一日地以sa来登录。为什么呢?或许,只花一、两分钟想一想就能想出,当使用sa账户时,在纯粹意外的情况下能够发生多少可怕的事情。使用sa意味着对任何事情都有完全的访问权,这就是说,当你在错误的数据库中执行DROP TABLE语句时,事实上,将按照你告知的那样去执行——删除那个表!!!对此,你只剩下说“哎呀!”了。而你的老板可能会说出完全不同的事情。
即使你确实需要总是拥有完全访问权,也应该只用sa账户让你的用户账户成为sysadmins服务器角色中的一员。那样做不仅赋予了你sa的权力,而且,单独的密码以及对当前是谁登录到系统中的审核跟踪(在跟踪工具Profiler中或者当查看系统活动时),使你获得了额外的安全性。
22.2.2 创建和管理登录
目前,要在SQL Server中创建登录名,有4种方式:
l 使用CREATE LOGIN;
l 使用Management Studio;
l SQL管理对象(SMO);
l 使用一些其他的选项,这些选项完全是为了向后兼容性而保留下来的。
1.CREATE LOGIN
CREATE LOGIN是SQL Server 2005中新增的语句,是微软为了让用来创建数据库和服务器对象的语法标准化所做的努力的一部分。不赞成使用sp_addlogin,在以前的版本中,sp_addlogin是用来添加登录名的过程化的方式,它看起来类似我们多次在SQL中见过的CREATE <object> <object type>语法,只是这里有一些额外的选项要求,这些选项要求是我们在诸如存储过程见过的。
最基本的语法是很简单明了的,但是,这些选项能够如何混合在一起,这一点则可能有些难于理解。整个语法如下所示:
CREATE LOGIN <登录名>
[ { WITH
PASSWORD = '<密码>' [ HASHED ] [ MUST_CHANGE ]
[, SID = <SID>
| DEFAULT_DATABASE = <数据库>
| DEFAULT_LANGUAGE = <语言>
| CHECK_EXPIRATION = { ON | OFF}
| CHECK_POLICY = { ON | OFF}
[ CREDENTIAL = <凭据名>
[, ... <下一选项>] ]
} |
{ FROM
WINDOWS
[ WITH DEFAULT_DATABASE = <数据库>
| DEFAULT_LANGUAGE = <语言> ]
| CERTIFICATE <证书名>
| ASYMMETRIC KEY <不对称密钥名>
}
]
紧接着登录名后,是选择FROM子句还是选择WITH子句,这是决定整个事情基调的关键部分,因此,我们结合属于FROM或WITH子句的选项来查看这些内容。
● CREATE LOGIN...WITH
WITH子句直接让你进入到与基于登录名的SQL Server身份验证有关的选项定义中,而非任何其他的验证方法。当激活了SQL Server安全性(相对于只是Windows安全性)时,它才是有关联的。这里的选项数量很多,看上去有些令人生畏,因此,把它们拆开来讲述。
这些选项中的大多数是真正全新的。好吧,当然,你会说:“我以为这整个命令都是新的?”是的,它的确是新的,但是,CREATE LOGIN...WITH本质上是CREATE LOGIN中取代了旧的sp_addlogin的部分。在SQL Server 2005中,即使是针对基于SQL Server的安全性,我们也极大改进了安全性选项,这反映在CREATE LOGIN...WITH中不存在于sp_addlogin里的选项上。
|
选 项 |
说 明 |
|
PASSWORD |
显然,该选项正像它听上去那样。这里要小心处理的地方是下面的问题:密码是明文的(在这种情况下,SQL Server将在添加密码时对密码进行加密),还是已经经过散列运算(在这种情况下,需要提供HASHED关键字,后面将讲述该关键字) |
|
HASHED |
该选项跟在密码后面,并且,仅当密码已经经过散列运算(加密)时才使用它。在那种情形下,SQL Server添加密码时不会再次对密码进行加密 |
|
MUST_CHANGE |
这又是一个可以“顾名思义”的选项。简言之,如果提供了该选项,那么,在用户首次登录时,将提示他们更改密码 |
|
SID |
你可以手工指定SQL Server使用什么GUID来验证这一登录名。如果未指定该选项(我认为这样做是一种极端的情况),则SQL Server将为你生成一个 |
|
DEFAULT_DATABASE |
这是该用户每次登录时的当前数据库 |
|
DEFAULT_LANGUAGE |
这是在给用户发送错误或者其他系统消息时所使用的语言 |
|
CHECK_EXPIRATION |
设置SQL Server是否强制实施密码过期策略。默认情况下,密码不会过期。若将该选项设置为ON,将强制密码过期策略 |
|
CHECK_POLICY |
设置SQL Server是否强制实施密码策略(长度、字符要求,等等)。默认情况下,密码必须满足Windows密码策略。如果把该选项设置为OFF,实际上将允许使用任何密码 |
|
CREDENTIAL |
指定该登录名将映射到的凭据名称(关于这是什么的问题,在后面将有更多的了解)。简言之,该选项把登录名映射到一组许可上,从而允许在SQL Server之外执行操作(如网络访问之类) |
所有这些选项都可以不提供,并且,仅在使用HASHED和MUST_CHANGE时(如果要使用它们,必须跟随在PASSWORD选项之后使用),提供选项的顺序才是要紧的。
● CREATE LOGIN...FROM
FROM子句表明,该登录名不是SQL Server专用的。FROM子句指定登录名的来源。来源分为几种不同的类别:
l WINDOWS——在这种情况下,我们把登录名映射到现有的windows登录名或组上。基本上,这是表示,“获取这个现有的Windows用户或组,并赋予它们访问SQL Server的权力。”你可以把SQL Server登录名映射到Windows组上,这表明,将把到SQL Server的那种级别的访问授予该组中所有的成员。实际上,这对于网络中的用户管理非常方便。例如,如果想要会计部门中的所有人在SQL Server中都拥有一组特定的权力,可以创建一个名为Accounting的Windows组,并把该组映射到一个SQL Server登录名。假如你新近雇用了某人,那么,一旦把他们加入到Accounting组中,他们不仅将获得Accounting组所拥有的Windows资源的访问权,而且,还将拥有Accounting组所拥有的所有SQL Server许可权限。
如果用Windows作为FROM的来源,那么,与基于SQL Server的登录名类似,你也可以提供一个WITH子句,只是这里局限于默认的数据库和语言。
l CERTIFICATE——这种登录名是基于X.509证书的,你已经通过CREATE CERTIFICATE命令将证书与服务器相关联。可以用几种不同的方式来使用证书,但最终,在本质上,它们将作为已认可的安全加密密钥。SQL Server有它自己的“证书颁发机构”,或者,也可以导入从其他的源产生的那些。本质上,需要提供证书作为登录到SQL Server中的授权。
l ASYMMETRIC KEY——非对称密钥与证书只是同一概念的两种方式。实质上,如果所给出的密钥是SQL Server信任的,则允许访问。非对称密钥只不过是表示安全密钥的另一种方法。
● ALTER LOGIN
像我们在SQL中见过的大多数CREATE语句一样,CREATE LOGIN有一个ALTER LOGIN形式的附加语句。像大多数ALTER语句一样,其语法主要是相关的CREATE语句中的选项的子集:
ALTER LOGIN <登录名>
[ { ENABLE | DISABLE } ]
[ { WITH
PASSWORD = '<密码>'
[ { OLD_PASSWORD = '<旧密码>'
| [ UNLOCK ] [ MUST_CHANGE ] }
| DEFAULT_DATABASE = <数据库>
| DEFAULT_LANGUAGE = <语言>
| NAME = <新的登录名>
| CHECK_EXPIRATION = { ON | OFF}
| CHECK_POLICY = { ON | OFF}
[ CREDENTIAL = <凭据名>
| NO CREDENTIAL
其中的大多数与它们在CREATE语句中完全一样,让我们来看一些不同之处。
|
选 项 |
说 明 |
|
ENABLE | DISABLE |
启用或禁用该登录。这有点像一个指示器,用以表示该登录在系统中是否被认为是活动的,另外,不要把ENABLE与UNLOCK混同起来(它们是不同的事情)。禁用登录时,登录依然在那里,只是不允许使用登录而已。启用将重新激活登录 |
|
OLD PASSWORD |
仅当指定的登录要使用ALTER LOGIN来更改它自己的密码时,该选项才适用。具有更改密码权限的安全管理员根本不可能知道旧的密码,并且,安全管理员无需了解旧密码,就拥有设置新密码的权限 |
|
UNLOCK |
当登录由于超过了设定的错误密码计数而被锁定时,该选项允许用户再次尝试登录 |
|
NAME |
该选项允许你更改登录名,然而,另一方面,将保留该登录所有旧的权限和其他属性 |
|
NO CREDENTIAL |
使登录与登录以前被映射到的所有凭据脱离开 |
● DROP LOGIN
该语句与SQL Server中其他的DROP语句类似。
DROP LOGIN <登录名>
执行语句后,登录就被删除了。
2.使用Management Studio创建登录
使用Management Studio创建登录账户非常简单,并且,这与创建SQL Server中大多数其他对象一样。只需要在“对象资源管理器”中导航到相应的结点(这里是“安全性”→“登录名”),右键单击,然后选择“新建登录名……”,如图22-1所示。

图 22-1
这将打开我们在本书中多次见过的典型的“新建”对话框,不过,这里的对话框针对适用于登录名的属性做了相应的调整,如图22-2所示。

图 22-2
图中,只有第一组属性(“常规”属性)可以映射到CREATE LOGIN语法。另外的选项卡将映射到其他的对象,我们将在本章接下来的讲述中创建这些对象。
我们将回顾其他几种以某种形式与登录名有关联的对象。眼下要注意的是,Management Studio中的用户界面是如何让你一次完成所有的事情的。在继续本书的讲述时将看到,当使用代码创建这些对象时,我们不得不分别完成每一步,而不能像Management Studio提供的那样一次完成全部的事情(正如你可能想象的,实际上,它不过是预先把所有必需的信息集中到一起,然后,为我们发出所有单独的程序化步骤)。
3.SQL管理对象
这超出了本章的范围(我们将在后面SMO自己的一章中涵盖其内容),但是,我确实想要特别指出,SMO能够使用直截了当的为对象模型创建登录账户,而不是使用CREATE语句这样的方法。更多相关内容请见第25章。
4.遗留选项
在以前版本的SQL Server中,当考虑创建登录账户的方法时,有3个较早的重要选择。
l sp_addlogin和相关的存储过程——除了CREATE LOGIN语句的几个部分所实现的事情在SQL Server 2000和更早的版本中不被支持外,本质上,sp_addlogin存储过程对应于CREATE LOGIN语句。不过,基本要素(创建典型的登录账户,而非证书或非对称密钥方法)都在这里。我们马上会更详尽地查看sp_addlogin。
l SQL-DMO——在SQL Server 2005中,已经完成了对分布式管理对象(DMO)的废除。这里说“完成”是因为,在SQL Server 2000面世的时候,WMI本来是做事情的一种新的方法——唔,它没有那样好。在2005的开发周期中尚早的时候,就决定了要使用一种更面向.NET的模型,于是,SMO诞生了。SMO自己就是一本书,并且,它完全超出了本书的范围。由此,可以把DMO想成是SMO出现之前的SMO。尽管模型有很大的差异,但是基本目的是相同的。
l WMI——Windows Management Instrumentation是工业标准Web管理协议的实现。正如我刚才说过的,在SQL Server 2000最初面世的时候,认为基于WMI的模型将接管成为自动化SQL Server管理的主要方式。最终,没有基于WMI的模型接近达到暴露我们在SQL Server中所需的所有事情的任务,而那样的努力似乎很大程度上也白费了。与DMO很类似,WMI眼下位于本书的范围之外,不过要认识到,当你需要管理较早版本的SQL Server时,它在那里并仍然是一种选择。
● sp_addlogin概览
该存储过程做的正是它所表达的事情,而且,它是一种旧的方法,它所实现的是今天由CREATE LOGIN为我们实现的事情。该存储过程必需的参数只有一个,但是,多数时候将使用2个或3个参数。这里有几个额外的参数,但是,它们极少被用到。该存储过程的语法如下:
EXEC sp_addlogin [@loginame =] <'登录名'>
[,[@passwd =] <'密码'>]
[,[@defdb =] <'数据库'>]
[,[@deflanguage =] <'语言'>]
[,[@sid =] 'SID']
[,[@encryptopt =] <'加密选择'>]
|
参 数 |
说 明 |
|
@loginame |
正如它听上去那样——这是要使用的登录ID |
|
@passwd |
更是如它听上去那样——用上述的登录ID进行登录时所使用的密码 |
|
@defdb |
默认数据库。该参数定义了用户登录时首先连接到的“当前的”数据库。通常,这将是应用程序使用的主要的数据库。如果不指定该参数,则默认数据库将是master数据库(你一般不想要这样,因此,务必要提供该参数) |
|
@deflanguage |
用户的默认语言。如果你支持本地化,可以使用该参数覆盖系统的默认值 |
|
@sid |
该参数是一个二进制数,它成为登录ID的安全标识号(SID)。如果不提供SID,SQL Server将为你生成一个。由于SID必须是唯一的,因此,提供的任何SID一定不能已经存在于系统中 当你在把数据库还原到不同的服务器上时,或者当迁移登录信息时,使用明确的SID能够十分便利 |
(续)
|
参 数 |
说 明 |
|
@encryptopt |
用户的登录ID和密码信息存储在master数据库中的sysusers表里。@encryptopt指定存储在master数据库中的密码是否加密。默认情况下(或者当在参数中提供NULL时),要对密码进行加密。另一个选择是skip_encryption,该值正如它所说明的那样——不对密码进行加密,而skip_encryption_old仅仅是为了向后兼容性,不应当再继续使用这一选项 |
正如你能够看出的,这里多数的项都直接映射到CREATE LOGIN,并且,如果不必为了向后兼容性的原因而使用sp_addlogin的话,建议你使用CREATE LOGIN方法来创建登录账户。
● sp_password
既然我们看了sp_addlogin,那么,我们应该看看sp_password。尽管ALTER LOGIN使你能够在登录上进行密码维护,sp_addlogin却没有这种功能——sp_password将处理那样的事情。其语法非常简单:
sp_password [[@old =] <'旧密码'>,]
[@new =] <'新密码'>
[,[@loginame =] <'登录名'>]
无疑,新密码和旧密码参数就像你期望的那样工作。你需要从用户那里接受它们,然后把它们传入存储过程中。然而,要注意,登录名是可选参数。如果不提供登录名,则将假定你想要在当前连接所使用的登录名上更改密码。注意,sp_password不能作为事务的一部分来执行。
你可能会想着这样的问题,“大多数系统都要求输入两次新密码,难道不是吗?”的确如此。那么,接下来的问题是,“为什么sp_password不这样做呢?”答案很简单——因为SQL Server把这一问题留待你来决定。你可以在客户端应用程序中包含一个逻辑,该逻辑在你使用sp_password之前,对两条新密码进行检查。对于ALTER LOGIN,也存在同样的问题。
● sp_grantlogin
该存储过程模拟了CREATE LOGIN...FROM与Windows登录有关的功能(由于此刻早于SQL Server 2005,因而源自证书和非对称密码的映射尚不存在)。其语法非常简单:
sp_grantlogin [@loginname = ]'<域名>\<Windows用户名>'
22.2.3 Windows集成的安全性
Windows安全性让我们能够把登录从信任的Windows域映射到SQL Server中。
这只是一种模式,在这种模式中,你取用现有的Windows域用户账户或组,并直接给它们提供SQL Server权限,而不是强迫用户保存单独的密码和进行单独的登录。
Windows安全性允许:
l 只从一个地方就能维护用户的访问;
l 只需简单地把用户加入到Windows组中,就能够授予用户SQL Server权限(这意味着,通常,为了准予用户访问,你甚至无需进入到SQL Server中);
l 用户只需记住一个密码和登录名即可。
不过,接下来,还是让我们看一下如何授予特定的用户特定的权限。






