EXECUTE AS, предложение (Transact-SQL)

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

В SQL Server можно определить контекст выполнения следующих пользовательских модулей: функции (за исключением встроенных табличных функций), процедур, очередей и триггеров.

Указав контекст, в котором выполняется модуль, можно управлять учетной записью пользователя, которую использует ядро СУБД для проверки разрешений на объекты, на которые ссылается модуль. Это повышает гибкость и безопасность управления разрешениями на цепочки владения между пользовательскими модулями и объектами, на которые они ссылаются. Тогда пользователям необходимо будет предоставлять только разрешения на сам модуль, без выдачи явных разрешений на объекты, на которые он ссылается. Только пользователь, от имени которого выполняется модуль, должен будет иметь разрешения на объекты, к которым этот модуль обращается.

Соглашения о синтаксисе Transact-SQL

Синтаксис

В этом разделе описывается синтаксис SQL Server для EXECUTE AS.

Функции (за исключением встроенных табличных функций), хранимых процедур и триггеров DML:

{ EXEC | EXECUTE } AS { CALLER | SELF | OWNER | 'user_name' }

Триггеры DDL с областью базы данных:

{ EXEC | EXECUTE } AS { CALLER | SELF | 'user_name' }

Триггеры DDL с областью сервера и триггерами входа:

{ EXEC | EXECUTE } AS { CALLER | SELF | 'login_name' }

Очереди.

{ EXEC | EXECUTE } AS { SELF | OWNER | 'user_name' }

Аргументы

ВЫЗЫВАЮЩИЙ

Указывает, что инструкции, содержащиеся в модуле, выполняются в контексте пользователя, вызывающего этот модуль. Пользователь, выполняющий модуль, должен иметь соответствующие разрешения не только на сам модуль, но также и на объекты базы данных, на которые имеются ссылки из этого модуля.

CALLER значение по умолчанию для всех модулей, кроме очередей, и совпадает с поведением SQL Server 2005 (9.x).

CALLERневозможно указать в инструкции или ALTER QUEUE инструкцииCREATE QUEUE.

SELF

EXECUTE AS SELF эквивалентен EXECUTE AS <user_name>тому, где указанный пользователь создает или изменяет модуль. Фактический идентификатор пользователя, создающего или изменяющего модули, хранится в столбце в execute_as_principal_id sys.sql_modules представлении каталога или sys.service_queues в представлении каталога.

SELF — значение по умолчанию для очередей.

Примечание.

Чтобы изменить идентификатор пользователя столбца execute_as_principal_id в sys.service_queues представлении каталога, необходимо явно указать EXECUTE AS параметр в инструкции ALTER QUEUE .

ВЛАДЕЛЕЦ

Указывает, что инструкции внутри модуля выполняются в контексте текущего владельца модуля. Если у модуля нет указанного владельца, используется владелец схемы модуля. OWNER нельзя указать для триггеров DDL или входа.

Внимание

OWNER должен сопоставляться с одной учетной записью и не может быть ролью или группой.

'user_name'

Указывает, что инструкции, содержащиеся в модуле, выполняются в контексте пользователя, указываемого аргументом user_name. Разрешения на объекты, на которые ссылается модуль, проверяются для user_name. user_name нельзя указать для триггеров DDL с областью сервера или триггерами входа. Вместо него следует использовать login_name.

Аргумент user_name должен присутствовать в текущей базе данных и не должен относиться к учетной записи группы. user_name не может быть группой, ролью, сертификатом, ключом или встроенной учетной записью, например NT AUTHORITY\LocalService, NT AUTHORITY\NetworkServiceили NT AUTHORITY\LocalSystem.

Идентификатор пользователя контекста выполнения хранится в метаданных и может просматриваться в столбце execute_as_principal_id в sys.sql_modules представлении каталога или sys.assembly_modules в представлении каталога.

"login_name"

Указывает инструкции внутри модуля, выполняемые в контексте имени входа SQL Server, указанного в login_name. Разрешения на объекты, на которые ссылается модуль, проверяются для login_name. Аргумент login_name можно указывать только для триггеров DDL в области сервера или триггеров входа.

login_name не может быть группой, ролью, сертификатом, ключом или встроенной учетной записью, например NT AUTHORITY\LocalService, NT AUTHORITY\NetworkServiceили NT AUTHORITY\LocalSystem.

Замечания

Как ядро СУБД оценивает разрешения для объектов, на которые ссылается модуль, зависит от цепочки владения, которая существует между вызывающими объектами и объектами, на которые ссылается ссылка. В более ранних версиях SQL Server цепочка владения была единственным способом, чтобы избежать необходимости предоставлять пользователю доступ ко всем объектам, на которые ссылается ссылка.

Цепочки владения имеют следующие ограничения.

  • Применяется только к операторам DML: SELECT, , UPDATEINSERTи DELETE.
  • У вызывающего и вызываемого объекта должен быть один и тот же владелец.
  • Не применяется к динамическим запросам внутри модуля.

Независимо от контекста выполнения, указанного в модуле, всегда выполняются следующие действия.

  • При выполнении модуля ядро СУБД сначала проверяет, имеет EXECUTE ли пользователь, выполняющий модуль, разрешение на модуль.

  • Применяются правила цепочки владения, то есть если вызывающий и вызываемый объекты имеют одного и того же владельца, разрешения на вложенные объекты не проверяются.

Когда пользователь выполняет модуль, который был указан для выполнения в контексте, отличном CALLERот разрешения пользователя на выполнение модуля, проверяется, но дополнительные разрешения проверяются на объекты, доступ к которым осуществляется модулем, выполняются в учетной записи пользователя, указанной в EXECUTE AS предложении. Пользователь, выполняющий модуль, таким образом олицетворяет указанного пользователя.

Контекст, указанный в EXECUTE AS предложении модуля, действителен только в течение срока выполнения модуля. после чего производится возврат в исходный контекст.

Указание имени пользователя или имени входа

Пользователь базы данных или имя входа сервера, указанное в EXECUTE AS предложении модуля, нельзя удалить, пока модуль не будет изменен для выполнения в другом контексте.

Имя пользователя или имени входа, указанное в EXECUTE AS предложении, должно существовать в качестве участника sys.database_principals или sys.server_principals, соответственно, или же происходит сбой операции создания или изменения модуля. К тому же пользователь, который создает или изменяет модуль, должен иметь разрешение IMPERSONATE на этого участника.

Если пользователь имеет неявный доступ к базе данных или экземпляру SQL Server через членство в группе Windows, пользователь, указанный в EXECUTE AS предложении, неявно создается при создании модуля при наличии одного из следующих требований:

  • Указанный пользователь или имя входа является членом предопределенной роли сервера sysadmin.
  • Пользователь, который создает модуль, имеет разрешение на создание участников.

Если какое-либо из этих условий не соблюдается, операция создания модуля завершается ошибкой.

Внимание

Если служба SQL Server (MSSQLSERVER) выполняется как локальная учетная запись (локальная служба или учетная запись локального пользователя), она не будет иметь привилегий для получения членства в группах учетной записи домена Windows, указанной в предложении EXECUTE AS . Это приведет к ошибке выполнения модуля.

Для примера рассмотрим следующие условия.

  • CompanyDomain\SQLUsers группа имеет доступ к Sales базе данных.

  • CompanyDomain\SqlUser1 является членом SQLUsers и поэтому имеет доступ к Sales базе данных.

  • Пользователь, который создает модуль, имеет разрешение на создание участников.

Когда следующее выражение CREATE PROCEDURE выполняется, выражение CompanyDomain\SqlUser1 безоговорочно создается в качестве базы данных субъекта в базе данных Sales .

USE Sales;
GO
CREATE PROCEDURE dbo.usp_Demo
WITH EXECUTE AS 'CompanyDomain\SqlUser1'
AS
SELECT USER_NAME();
GO

Использование автономной инструкции EXECUTE AS CALLER

EXECUTE AS CALLER Используйте автономную инструкцию внутри модуля, чтобы задать контекст выполнения вызывающей части модуля.

Рассмотрим следующую хранимую процедуру под названием SqlUser2.

CREATE PROCEDURE dbo.usp_Demo
WITH EXECUTE AS 'SqlUser1'
AS
SELECT USER_NAME(); -- Shows execution context is set to SqlUser1.
EXECUTE AS CALLER;
SELECT USER_NAME(); -- Shows execution context is set to SqlUser2, the caller of the module.
REVERT;
SELECT USER_NAME(); -- Shows execution context is set to SqlUser1.
GO

Использование EXECUTE AS для определения пользовательских наборов разрешений

Указание контекста выполнения для модуля может оказаться полезным, если требуется определить пользовательские наборы разрешений. Например, некоторые действия, такие как TRUNCATE TABLE не имеют предоставленных разрешений. Включив TRUNCATE TABLE инструкцию в модуль и указав, что модуль выполняется как пользователь, имеющий разрешения на изменение таблицы, можно расширить разрешения для усечения таблицы пользователю, которому вы предоставляете EXECUTE разрешения на модуль.

Для просмотра определения модуля вместе с указанием контекста выполнения воспользуйтесь представлением каталога sys.sql_modules (Transact-SQL).

Рекомендация

Указывайте имя входа или пользователя, имеющего минимальные права на выполнение операций, определенных в модуле. Например, не указывайте учетную запись владельца базы данных, если эти разрешения не требуются.

Разрешения

Чтобы выполнить модуль, указанный с EXECUTE ASпомощью, вызывающий объект должен иметь EXECUTE разрешения на модуль.

Чтобы выполнить модуль CLR, указанный с EXECUTE as, который обращается к ресурсам в другой базе данных или сервере, целевая база данных или сервер должны доверять аутентификатору базы данных, из которой создается модуль (исходная база данных).

Чтобы указать EXECUTE AS предложение при создании или изменении модуля, необходимо иметь IMPERSONATE разрешения на указанный субъект, а также разрешения для создания модуля. Пользователь всегда может олицетворять сам себя. Если контекст выполнения не указан или EXECUTE AS CALLER не указан, IMPERSONATE разрешения не требуются.

Чтобы указать login_name или user_name с неявным доступом к базе данных через членство в группе Windows, необходимо иметь CONTROL разрешения на базу данных.

Примеры

В следующем примере создается хранимая процедура в базе данных AdventureWorks2022 и назначается контекст OWNERвыполнения.

CREATE PROCEDURE HumanResources.uspEmployeesInDepartment @DeptValue INT
    WITH EXECUTE AS OWNER
AS
SET NOCOUNT ON;

SELECT e.BusinessEntityID,
    c.LastName,
    c.FirstName,
    e.JobTitle
FROM Person.Person AS c
INNER JOIN HumanResources.Employee AS e
    ON c.BusinessEntityID = e.BusinessEntityID
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
    ON e.BusinessEntityID = edh.BusinessEntityID
WHERE edh.DepartmentID = @DeptValue
ORDER BY c.LastName,
    c.FirstName;
GO

-- Execute the stored procedure by specifying department 5.
EXECUTE HumanResources.uspEmployeesInDepartment 5;
GO