微软BI开拓者数据库专区SQL Server管理 SQLServer中的所有权链是安全还是风险

1  /  1  页   1 跳转 查看:854

[技术文档] SQLServer中的所有权链是安全还是风险

SQLServer中的所有权链是安全还是风险

SQLServer中的所有权链是安全还是风险

--王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com
--原帖地址



问题


我曾听说过SQLServer里的所有权链,但我不懂它是什么、它是如何运作的。我想知道它是安全还是风险,如果安全,我怎样使用它。如果是风险,我想知道如何避免它。


解决方法

所有权链在SQLServer里安全的,不是风险。所有的对象如表和视图都有所有者。在SQLServer2005以及以后的版本里,所有者可以间接来自于对象所属的架构的所有者。让我们来详细的看看。

每个对象都包含在一个架构里。SQLServer2005SQLServer2008里的架构用来把一组对象放进逻辑容器中。例如,对一个特定的应用程序而言,在公司内可能有2类用户,一些来自市场而另外一些来自人力资源。一些对象如针对员工的表,逻辑上适合放在与人力资源类型对象相关的容器里。其他对象适合放在与市场相关对象的容器里,如记录广告运营的表。通过使用架构,可以根据目的来分组对象。作为一个例子,我们可以创建2个这样的架构:

CREATE SCHEMA Marketing;
GO

CREATE SCHEMA HumanResources;
GO



架构必须有所有者。如果当架构创建的时候没有指定所有者(使用AUTHORIZATION关键字来执行所有者),那么创建架构的用户就是所有者。我们可以使用下面的查询来查看数据库里的架构和它们的所有者:

SELECT 
   
[name] AS [schema] 
 
, [schema_id]
 
, USER_NAME(principal_id) [Owner]
FROM sys.schemas;


这里是数据库AdventureWorks数据库的输出结果:



SQLServer2005/2008中,当创建一个对象的时候,不必指定所有者。SQLServer将假定对象的所有者就是对象所属架构的所有者。例如,在下面的对象创建语句里,没有指定所有者。因此,那些对象的所有者相当于那些对象所属架构的所有者:

CREATE TABLE HumanResources.TestTable (
 
TableValue INT 
);
GO

CREATE PROC Marketing.QueryTestTable
AS
BEGIN
  SELECT
TableValue FROM HumanResources.TestTable;
END
GO



第一个对象,一个叫TestTable的表,创建在了架构HumanResources里。第二个对象,一个叫QueryTestTable的存储过程,创建在了架构Marketing里。由于没有其他的T-SQL命令来指定其他对象的所有者,SQLServer在考虑所有权链时将使用各自架构的所有者作为对象的所有者。对象可以通过使用ALTER AUTHORIZATION来明确指定所有者,如这里显示的(CREATE USER语句创建了一个合法用户来作为创建的表的所有者):

CREATE USER TestUser WITHOUT LOGIN;
GO

CREATE TABLE Marketing.OwnedTable (
 
TableValue INT
);
GO

ALTER AUTHORIZATION ON Marketing.OwnedTable TO TestUser;
GO


我们可以通过查询sys.objectssys.schemas来得到对象、对象所属的架构,以及对象的有效所有者。如果没有明确指定对象所有者,那么sys.objectsprincipal_id列将为NULL。通过使用COALESCE,我们可以通过先查看sys.objectsprincipal_id再查看sys.schemasprincipal_id来实际决定所有者。


SELECT 
   
so.[name] AS [Object]
 
, sch.[name] AS [Schema]
 
, USER_NAME(COALESCE(so.[principal_id], sch.[principal_id])) AS [Owner]
 
, type_desc AS [ObjectType]
FROM sys.objects so
 
JOIN sys.schemas sch
   
ON so.[schema_id] = sch.[schema_id]
WHERE [type] IN ('U', 'P');



这里是AdventureWorks数据库里的头几条数据:


一旦我们理解了一个对象的有效所有者是谁,我们就可以来看看所有权链了。当满足下列条件时就会发生所有权链:
  • 一个对象引用了另一个对象,如存储过程引用了表
  • 两个对象都有相同的所有者

在这样的情形下,一个用户仅需有第一个对象的权限。例如,用早先的那个存储过程Marketing.QueryTestTable来说,它查询了表HumanResource.TestTable。如果两个对象的所有者是相同的,那么一个所有权链就形成了。当一个所有权链形成的时候,SQLServer将只检查第一个对象的权限。因为所有者是相同的,它就假定引用是有意的,并且不会检查引用对象的权限。因此,在这个例子中,如果一个用户有权限去执行Marketing.QueryTestTableSQLServer将允许查询表HumanResource.TestTable,只要这个查询是通过这个存储过程执行的。


例如,如果我们要控制对那个表的访问以便只能通过存储过程来进行的话,这个例子用T-SQL创建一个角色并分配给角色需要的权限:


CREATE ROLE GrantPermissions;
GO

GRANT EXECUTE ON Marketing.QueryTestTable TO GrantPermissions;
GO


通过所有权链的使用,我们可以强迫使用存储过程来访问。这是有利的,比如我们要控制怎样让表里的数据插入、更新或删除。一个好的例子是应用程序一次删除一行数据。明确地给定了一个用户对表的访问权限,那个用户可能因为忘记使用where语句而意外的删除表的所有数据。解决方法就是创建一个存储过程,让它删除基于传入参数的特定的行。存储过程仅允许删除一行。这样,终端用户就不能意外的删除所有的记录了,因为用户没有针对表的权限。用户会试着删除,但他会得到一个访问被拒绝的错误。然而,用户可以执行存储过程,但这样做就仅限于存储过程所影响的范围内了。这就是所有权链的好处。


下一篇文章将在本文的基础上,讲解跨数据库所有权链。
最后编辑拓狼 最后编辑于 2009-07-02 17:57:55
虽有智慧,不如乘势;虽有鎡基,不如待时。
君子学以聚之,问以辨之,宽以居之,仁以行之。
独学而无友,则孤陋而寡闻。
 

回复:SQLServer中的所有权链是安全还是风险

学习了!
 
1  /  1  页   1 跳转

版权所有 微软BI开拓者 

Powered by Discuz!NT 2.1.202    Copyright © 2001-2010 Comsenz Inc.
Processed in 0.0468756 second(s) , 3 queries.
返顶部