日期:2013-01-31  浏览次数:20608 次

  执行环境是SQL Server中设定用户权限的认证方式,例如,当您登录到SQL Server的时候,登录账户就被赋予了一定的权限,其中可能包括登录的功用、访问数据库以及在数据库中执行某些操作的功用。

  SQL Server 2005包含了EXECUTE AS语句,通过使用EXECUTE AS语句,您可以为批处理和过程转换执行环境,这样,调用该批处理或过程的用户就可以使用不同的权限来操作了。

  所有权链

  在我正式讲解SQL Server 2005中执行环境的问题之前,先来简单地说说所有权链的任务原理。

  当用户执行一个存储过程的时候(假定该用户拥有执行该存储过程的权限),SQL Server将该存储过程的所有者与这个存储过程所涉及到的对象的所有者进行对比,如果他们的所有者相反,那么就不必对这些援用对象的权限进行评估了。

  所以,如果用户Tim获得了存储过程usp_ProcedureChain的权限,而usp_ProcedureChain存储过程的所有者是dbo,那么,如果dbo还同时拥有usp_ProcedureChain所调用的其他存储过程,那么Tim在执行这个存储过程的时候就不会出现错误。

  执行环境的转换

  在SQL Server 2000中,您可以使用SETUSER命令来模仿SQL用户的执行环境,但问题在于,只要系统管理员或者数据库的所有者才能使用这个命令,而且Windows账户也不能使用该命令。

  在SQL Server 2005中,EXECUTE AS语句可以替代SETUSER来改变存储过程、触发器、批处理或者函数的执行环境。如果执行环境变成了另外一个用户,那么SQL Server将检查该用户的权限。如果您需求在创建或修正一个存储过程或函数的时候指定EXECUTE AS语句,您需求具备IMPERSONATE的权限,以及创建该对象的权限。

  实例

  正如我刚才所引见的一样,改变存储过程的执行环境非常有用,接下来我将通过实例来讲解如何实现这一功用。在这个例子中,您会看到如何使用EXECUTE AS将没有确切权限的使用者模仿为所有者对表格进行插入操作。

  在第一行语句中,我使用了REVERT命令,这样,您就可以完整地前往到例子中,而不必担心需求清除任何对象。

REVERT
GO

  在下面的代码的第七行,我使用了清除语句,这样可以检查我在随后的例子中要使用的对象能否曾经存在,如果曾经存在,就将其清除。

IF OBJECT_ID('usp_InsertMyTable','P')>0
DROP PROCEDURE usp_InsertMyTable
GO
IF OBJECT_ID('TableOwnerSchema.MyTable','U')>0
DROP TABLE TableOwnerSchema.MyTable
GO
IF EXISTS
(SELECT * FROM sys.schemas WHERE name = N'TableOwnerSchema')
DROP SCHEMA [TableOwnerSchema]
IF EXISTS
(SELECT * FROM sys.database_principals WHERE name = N'BaseUser')
DROP USER BaseUser
IF EXISTS
(SELECT * FROM sys.server_principals WHERE name = N'BaseUser')
DROP LOGIN BaseUser
IF EXISTS
(SELECT * FROM sys.database_principals WHERE name = N'TableOwner')
DROP USER TableOwner
IF EXISTS
(SELECT * FROM sys.server_principals WHERE name = N'TableOwner')
DROP LOGIN TableOwner

  以下的脚本语句创建了两个登录名和数据库的用户账户,留意,CHECK_EXPIRATION和CHECK_POLICY语句,这两条语句是SQL Server 2005中新出现的。这些语句通知SQL Server不要对这个用户账户强制执行密码截止期限策略,同时也不要进行任何类型的密码策略检查,对于强制安全策略而言,这些是非常无效的方法。

CREATE LOGIN [BaseUser] WITH PASSWORD=N'baseuser',
DEFAULT_DATABASE=[TRS],
CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
CREATE USER [BaseUser] FOR LOGIN [BaseUser]
GO
CREATE LOGIN [TableOwner] WITH PASSWORD=N'tableowner',
DEFAULT_DATABASE=[TRS],
CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
CREATE USER TableOwner FOR LOGIN TableOwner
GO

  在SQL Server 2005中,模式不再是和数据库用户相反的事情了,对于所包含的对象而言,它处于完全不同的名称空间。用户和模式的分离是SQL Server 2005中的一大进步,这样做使对象的所有权可以分离,而且比SQL Server 2000更易于管理,以下的语句创建了我们将要使用的数据库模式:

CREATE SCHEMA [TableOwnerSchema] AUTHORIZATION [TableOwner]
GO
Now I enable logins so they can be used:
ALTER LOGIN [TableOwner] ENABLE
ALTER LOGIN [BaseUser] ENABLE
GO
GRANT CREATE TABLE TO TableOwner
GO

  首先,我使用了EXECUTE AS命令,我将当前的执行环境设定为TableOwner,在运转了这个命令之后,所有的权限评估将以TableOwner运转,而以前的系统管理员权限将不再适用。

EXECUTE AS USER = 'TableOwner'
GO

  运转这个语句就能够表明如今的执行环境是TableOwner:

SELECT SESSION_USER
GO

  这个脚本将在TableOwnerSchema的模式中创建一个名为MyTable的表格,由于我曾经赋予了该用户CREATE TABLE 的权限,所以TableOwner可以执行这条语句。

CREATE TABLE TableOwnerSchema.MyTable
(
Field1 INT
)
GO

  当我运转REVERT语句的时候,可以在执行环境链中回退一步,在SQL Server 2005中,执行环境是可以嵌套的,所以如果您在同一个数据库连接中有很多用户在运转,您可能需求多次执行该语句以前往到原始的登录环境。

REVERT
GO
SELECT SESSION_USER
GO

  如今我要对新的表格进行快速选择以确认它的存在:

SELECT * FROM TableOwnerSchema.MyTable
GO

  以下的脚本创建了一个过程可以插入新的TableOwnerSchema.MyTable表格,留意我在过程定义中使用了WITH EXECU