MS SQL Server: проверьте, может ли пользователь выполнить хранимую процедуру.

Как вы можете проверить, может ли пользователь выполнить хранимую процедуру на сервере MS SQL?

Я могу увидеть, есть ли у пользователя явные разрешения на выполнение, подключившись к базе данных master и выполнив:

databasename..sp_helpprotect 'storedProcedureName', 'username'

однако, если пользователь является членом роли с разрешениями на выполнение, sp_helprotect мне не поможет.

В идеале я хотел бы иметь возможность вызывать что-то вроде

databasename..sp_canexecute 'storedProcedureName', 'username'

который вернет логическое значение.


person Andrew    schedule 27.01.2009    source источник
comment
Кроме того, если вы используете SQL Server 2005 или более позднюю версию и разрешение назначено схеме или базе данных (теперь может быть EXECUTE), процедура sp_helprotect не сообщит об этом. Хранимая процедура включена только для обратной совместимости и сообщает о разрешениях на основе того, что было в SQL Server 2000.   -  person K. Brian Kelley    schedule 27.01.2009


Ответы (3)


fn_my_permissions и HAS_PERMS_BY_NAME

person Cade Roux    schedule 27.01.2009
comment
Я не думаю, что эти функции отвечают на первоначальный вопрос, который заключался в том, чтобы проверить, имеет ли какой-либо данный пользователь права на выполнение данного хранимого процесса. В статьях MSDN для обеих функций говорится, что они возвращают разрешения для только вызывающего участника, а не для любого участника. - person Simon Tewsi; 21.03.2017

Попробуйте что-то вроде этого:

CREATE PROCEDURE [dbo].[sp_canexecute]
@procedure_name varchar(255),
@username varchar(255),
@has_execute_permissions bit OUTPUT
AS

IF EXISTS (
        /* Explicit permission */
        SELECT 1
        FROM sys.database_permissions p
        INNER JOIN sys.all_objects o ON p.major_id = o.[object_id] AND o.[name] = @procedure_name
        INNER JOIN sys.database_principals dp ON p.grantee_principal_id = dp.principal_id AND dp.[name] = @username
    )
    OR EXISTS (
        /* Role-based permission */
        SELECT 1
        FROM sys.database_permissions p
        INNER JOIN sys.all_objects o ON p.major_id = o.[object_id]
        INNER JOIN sys.database_principals dp ON p.grantee_principal_id = dp.principal_id AND o.[name] = @procedure_name
        INNER JOIN sys.database_role_members drm ON dp.principal_id = drm.role_principal_id
        INNER JOIN sys.database_principals dp2 ON drm.member_principal_id = dp2.principal_id AND dp2.[name] = @username
    )
BEGIN
    SET @has_execute_permissions = 1
END
ELSE
BEGIN
    SET @has_execute_permissions = 0
END
GO
person Dane    schedule 27.01.2009
comment
Работает ли это, если пользователь является членом роли с разрешениями, и ему явно не разрешено выполнять хранимую процедуру? - person Andrew; 28.01.2009
comment
Нет, но вы можете указать имя роли в параметре @username, и это все равно вернет правильный/ожидаемый логический результат. - person Dane; 29.01.2009
comment
Хорошо, я обновил приведенный выше код процедуры, чтобы получить разрешения, предоставленные в виде ролей, а также явное предоставление. - person Dane; 29.01.2009
comment
Я не думаю, что при этом учитываются разрешения, предоставленные через родительские разрешения, например, если у пользователя есть разрешения на выполнение для всей этой схемы, но не непосредственно для этого элемента. Это точно? - person Maslow; 19.02.2014

Предполагая, что SP выполняет только оператор SELECT:

ВЫПОЛНИТЬ КАК ПОЛЬЗОВАТЕЛЬ = [ID/логин пользователя]
EXEC sp_foobar( sna, fu)
REVERT

Важно отметить, что вам нужно будет запустить команду REVERT после приглашения, поскольку SQL Server будет рассматривать вас как пользователя, КАК ВЫПОЛНЯЕТСЯ, пока вы не отключите соединение или не вернете олицетворение. Тем не менее, вы должны точно видеть, что получит пользователь (получение некоторых строк, но не всех? Это должно вам помочь).

person Pulsehead    schedule 27.01.2009