none
需要什么权限才能执行一个存储过程? RRS feed

  • 常规讨论

  • 常常有人问到,我已经拥有一个存储过程上的EXECUTE权限,但是有时候执行这个存储过程时,执行时还是会遇到权限错误。例如下面这个实例:
    USE master;
    GO
    -- 创建个测试登入用户和一个测试数据库
    CREATE LOGIN login1 WITH PASSWORD = 'Pa$$w0rd';
    CREATE LOGIN login2 WITH PASSWORD = 'Pa$$w0rd';
    CREATE DATABASE ProcTestDB;
    GO

    -- 把执行环境移到测试数据库
    USE ProcTestDB;
    GO

    -- 创建个测试数据库用户
    CREATE USER user1 FOR LOGIN login1;
    CREATE USER user2 FOR LOGIN login2;
    GO

    -- 创建个测试数据库架构
    -- sch1的所有者为user1
    -- sch2的所有者为user2
    CREATE SCHEMA sch1 AUTHORIZATION user1;
    GO
    CREATE SCHEMA sch2 AUTHORIZATION user2;
    GO

    -- 创建个测试表,分别在不同的架构下
    CREATE TABLE sch1.tbl1
    (ID int, Name nvarchar(20));
    GO
    CREATE TABLE sch2.tbl2
    (ID int, Name nvarchar(20));
    GO

    -- 在sch1架构下,创建个测试存储过程
    CREATE PROCEDURE sch1.GetAllRowsOftbl1
    AS
    SELECT * FROM sch1.tbl1;
    GO
    CREATE PROCEDURE sch2.GetAllRowsOftbl1
    AS
    SELECT * FROM sch1.tbl1;
    GO

    -- 把sch1.GetAllRowsOftbl1是的EXECUTE权限给user2
    -- 因为user2是sch2的所有者,因此具有在sch2.GetAllRowsOftbl1的EXECUTE权限
    GRANT EXECUTE ON sch1.GetAllRowsOftbl1 TO user2;


    -- 以login2的登入用户身份执行
    EXECUTE AS LOGIN = 'login2';
    GO
    -- Test 1
    EXEC sch1.GetAllRowsOftbl1;
    GO
    -- Test 2
    EXEC sch2.GetAllRowsOftbl1;
    GO
    -- 退出login2然后删除所有对象
    REVERT
    GO

    -- 把sch1.tbl1上的SELECT权限赋给user2
    GRANT SELECT ON sch1.tbl1 TO user2;
    GO

    -- 以login2的登入用户身份执行
    EXECUTE AS LOGIN = 'login2';
    GO
    -- Test 3
    EXEC sch2.GetAllRowsOftbl1;
    GO
    -- 退出login2然后删除所有对象
    REVERT
    GO

    USE master;
    GO
    DROP LOGIN login1;
    DROP LOGIN login2;
    DROP DATABASE ProcTestDB;

    此时login2拥有sch1.GetAllRowsOftabl1和sch2.GetAllRowsOftabl1二个存储过程的EXECUTE权限,能顺利执行前者,而执行第后者却出现以下错误:

     
    这个问题是跟所有权链(Ownership Chains)有关。通过链访问对象时,SQL Server 首先将对象的所有者与调用对象的所有者进行比较。调用对象指链中的上一个链接。如果两个对象的所有者相同,则不评估对被引用对象的权限。在第一个测试中sch1.GetAllRowsOftbl1与sch1.tbl1是同一个所有者user1,所在当user2执行该存储过程时,不会评估user2是否有sch1.tbl1上的SELECT权限。而在第二个测试中,由于sch2.GetAllRowsOftbl1与sch1.tbl1的所有者不同(前者是user2,后者是user1),因此当user2执行该存储过程时,则会评估user2是否有sch1.tbl1上的SELECT权限,而这时user2不具有该权限,所以产生以上错误。解决这个问题,我们需要额外的把sch1.tbl1上的SELECT权限赋给user2便可以解决这个问题,如第三个测试。

    参考:
    所有权链
    http://msdn.microsoft.com/zh-cn/library/ms188676.aspx

    2012年1月6日 1:13
    版主