Chọn quyền trong thủ tục lưu trữ?


8

Tôi đã cấp cho người dùng quyền thực thi cho một thủ tục được lưu trữ sử dụng SQL động. Nhưng khi anh ta cố gắng thực hiện nó, anh ta đã gặp lỗi:

Quyền SELECT đã bị từ chối trên đối tượng '[tên bảng]', cơ sở dữ liệu '[tên cơ sở dữ liệu]', lược đồ 'dbo'.

Người dùng có cần được cấp quyền cho bất kỳ bảng nào mà quy trình được lưu trữ sử dụng không? Điều đó sẽ không thực sự có ý nghĩa với tôi.

Câu trả lời:


5

Ok, trên cơ sở nhận xét trên và theo sự nghi ngờ của tôi - có vẻ như bạn đang cố thực thi SQL động trong quy trình được lưu trữ của mình.

Điều bạn cần nhớ là khi bạn thực hiện việc này, nó không được thực thi trong ngữ cảnh của thủ tục được lưu trữ - nó sẽ được thực thi trong một phiên mới. Do đó, thực tế là câu lệnh đang được gọi trong một thủ tục được lưu trữ là một điểm cần thiết và bạn sẽ cần cấp quyền rõ ràng cho các đối tượng mà SQL động của bạn đang sử dụng.

Nếu bạn không muốn làm điều này, tôi sẽ cấu trúc lại thủ tục được lưu trữ của bạn để không sử dụng SQL động.

Liên kết dưới đây từ Microsoft sẽ giúp bạn giải quyết vấn đề của mình:

PRB: Bối cảnh bảo mật của các câu lệnh SQL động bên trong một thủ tục được lưu trữ (lưu trữ máy Wayback)

Hành vi này xảy ra vì một truy vấn thực thi động (sp_executesql hoặc EXECUTE) thực thi trong một bối cảnh riêng biệt từ thủ tục được lưu trữ chính; nó thực thi trong ngữ cảnh bảo mật của người dùng thực thi thủ tục được lưu trữ chứ không phải trong bối cảnh bảo mật của chủ sở hữu của thủ tục được lưu trữ.

Điều này cũng được thảo luận trong bài viết (hiện tại) của Microsoft Docs:

Viết SQL động an toàn trong SQL Server

Việc thực thi các câu lệnh SQL được tạo động trong mã thủ tục của bạn sẽ phá vỡ chuỗi quyền sở hữu, khiến SQL Server kiểm tra các quyền của người gọi đối với các đối tượng được SQL động truy cập.


2

Có vẻ như có chủ sở hữu khác nhau của thủ tục cũng như đối tượng cơ bản mà CHỌN đang truy vấn. Tất cả điều này phải làm với Chuỗi sở hữu . Xem ví dụ dưới đây để được giải thích ngắn gọn và trình diễn về những gì tôi đang nói về:

use YourTestDatabase;
go

create login TestLogin1
with 
    password = 'password',
    check_policy = off;
go

create user TestUser1
for login TestLogin1;
go

create table Table1
(
    id int identity(1, 1) not null,
    SomeString varchar(30) not null
        default replicate('a', 30)
);
go

insert into Table1
values(default);
go 10

create proc Proc1
as
    select *
    from Table1;
go


grant execute
on Proc1
to TestUser1;
go

-- this works because permissions aren't checked
--  on Table1.  That is why TestUser1 can get the
--  result set without SELECT permissions on Table1
execute as user = 'TestUser1';
go

exec Proc1;
go

revert;
go

-- let's change the owner of Proc1 so that the 
--  ownership chain is broken and permissions are
--  checked on Table1
alter authorization
on Proc1
to TestUser1;
go

-- this no longer works because permissions are now
--  checked on Table1, which TestUser1 does not have
--  SELECT permissions on
execute as user = 'TestUser1';
go

exec Proc1;
go

revert;
go

Nếu bạn muốn tìm hiểu quyền sở hữu đối tượng của mình, bạn có thể chạy truy vấn bên dưới (rõ ràng là thay đổi mệnh đề WHERE để bao gồm tên đối tượng cụ thể của bạn):

select
    o.name,
    o.type_desc,
    case
        when o.principal_id is null
            then sp.name
        else dp.name
    end as principal_name
from sys.objects o
inner join sys.schemas s
on o.schema_id = s.schema_id
left join sys.database_principals dp
on o.principal_id = dp.principal_id
left join sys.database_principals sp
on s.principal_id = sp.principal_id
where o.name in
(
    'Table1',
    'Proc1'
);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.