MSSQLSERVER_15517

Aplica-se a: SQL Server

Detalhes

Attribute Valor
Nome do Produto SQL Server
ID do Evento 15517
Origem do evento MSSQLSERVER
Componente SQLEngine
Nome simbólico SEC_CANNOTEXECUTEASUSER
Texto da mensagem Não pode ser executado como principal da base de dados porque o principal "principal" não existe, este tipo de principal não pode ser imitado, ou não tem permissão.

Explanation

Este erro ocorre normalmente porque o Microsoft SQL Server não consegue obter a informação sobre o contexto de execução do principal especificada numa instrução ou módulo de utilizador usando essa EXECUTE AS instrução.

A sua informação de login, Identificador de Segurança (SID), é automaticamente guardada quando cria uma base de dados numa instância do SQL Server como proprietário da base de dados na linha correspondente da sys.databases tabela e para o dbo item de utilizador na sys.database_principals tabela dentro da base de dados.

As instruções ou módulos que usam a EXECUTE AS OWNER cláusula funcionarão como esperado se a entrada SID armazenada para o utilizador dbo for válida.

Note

O problema pode ocorrer para qualquer princípio usado na EXECUTE AS instrução e que não exista no servidor onde a base de dados é restaurada.

Aqui estão alguns cenários comuns que podem causar este problema:

  • Restauras uma base de dados na mesma instância do servidor onde o backup foi originalmente feito, mas o princípio do SQL Server que criou a base de dados já não é válido por algum motivo. Por exemplo:

    • O login de autenticação do SQL Server foi removido.
    • O login do Windows authentication já não é para um utilizador válido no Active Directory porque o funcionário saiu da empresa.
  • Restauras uma base de dados num servidor que é diferente da instância onde o backup foi originalmente feito, mas o princípio do SQL Server que criou a base de dados não é válido no novo servidor.

    • Se o utilizador for um login do SQL Server, o principal pode existir no servidor de destino ou de destino, mas o sid valor será diferente.
    • Se o utilizador for um login do Windows, o login do Windows deixa de existir no servidor de destino ou deixa de ser válido.

O utilizador ou aplicação que executa o procedimento, função ou trigger armazenado não tem as permissões necessárias para se fazer passar pelo principal especificado na EXECUTE AS instrução.

Ação do usuário

Use o nome de um principal existente ou conceda permissão ao IMPERSONADO sobre esse principal aos utilizadores necessários.

Para resolver o problema que ocorre devido a um erro inválido do utilizador do dbo, altere o dbo_User valor para um login válido no seu servidor executando o seguinte comando:

ALTER AUTHORIZATION ON DATABASE:: DBName TO [NewLogin]  

Cenário de exemplo

  1. Crie dois princípios temporários:

    CREATE LOGIN login1 WITH PASSWORD = 'J345#$)thb';
    CREATE LOGIN login2 WITH PASSWORD = 'Uor80$23b';
    
  2. Adicione estes logins ao papel de sysadmin (apenas para demonstração).

  3. Inicie sessão na sua instância do SQL Server usando login1.

  4. Crie uma base de dados de demonstração e um procedimento armazenado que seja nomeado testexec executando o seguinte script:

    CREATE DATABASE Demodb_15517
    GO
    USE Demodb_15517
    GO
    CREATE procedure [dbo].[testexec]
    WITH EXECUTE AS owner
    AS SELECT @@VERSION
    GO
    EXEC dbo.testexec
    GO
    
  5. Execute as seguintes consultas e verifique se os sid valores estão a resolver para um login válido:

    • Consulta 1: Verifique o valor do Owner_Name valor em sys.databases.

      SELECT NAME AS Database_Name, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
      FROM sys.databases
      WHERE NAME = N'Demodb_15517';
      
      Database_Name         owner_sid                               OwnerName
      --------------------- -------------------------------------- ----------------------------
      Demodb_15517          0xDB79ED7B6731CF4E8DC7DF02871E3E36      login1
      
    • Consulta 2: Verifique o Owner_Name valor na sys.database_principals tabela dentro da base de dados de demonstração:

      SELECT SUSER_SNAME(sid) AS Owner_Name, sid 
      FROM Demodb_15517.sys.database_principals 
      WHERE NAME = N'dbo'; 
      
      Owner_Name    SID
      ------------- ------------------------------------------------ 
      login1        0xDB79ED7B6731CF4E8DC7DF02871E3E36
      
  6. Faça backup da base de dados de demonstração usando uma consulta que se assemelhe ao seguinte script:

    BACKUP DATABASE [Demodb_15517] TO DISK = N'C:\SQLBackups\Demodb_15517.bak' WITH NOFORMAT, NOINIT, NAME = N'Demodb_15517 Full backup', SKIP, EWIND, NOUNLOAD, STATS = 10 
    GO
    
  7. Abandone a base de dados de demonstrações e login1:

    DROP DATABASE demodb_15517
    GO
    DROP login login1
    GO
    
  8. Inicie sessão no SQL Server como login2.

  9. Restaure a base de dados de demonstração a partir do backup usando uma instrução que se assemelhe ao seguinte script:

    USE [master] 
    RESTORE DATABASE [Demodb_15517] FROM   
    DISK = N'C:\SQLBackups\Demodb_15517.bak' WITH FILE = 1,   
    MOVE N'Demodb_15517' TO N'C:\SQLBackups\Demodb_15517.mdf',   
    MOVE N'Demodb_15517_log' TO N'C:\SQLBackups\\Demodb_155172_log.ldf',   
    NOUNLOAD, STATS = 5 
    GO 
    
  10. Reexecute a Consulta 1 e a Consulta 2.

  11. Na Consulta 1, verifique o valor do Owner_Name valor em sys.databases. O valor agora reflete login2.

    SELECT NAME AS Database_Name, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName 
    FROM sys.databases 
    WHERE NAME = N'Demodb_15517';
    
    Database_Name  owner_sid                               OwnerName
    -------------- --------------------------------------- ---------------------
    Demodb_15517   0xD63086DD7277BC4EB88013D359AF73A6      login2
    
  12. Na Consulta 2, verifique o valor do Owner_Name valor na sys.database_principals tabela dentro da base de dados de demonstração. O valor agora reflete NULL.

    SELECT SUSER_SNAME(sid) AS Owner_Name, sid
    FROM Demodb_15517.sys.database_principals
    WHERE NAME = N'dbo';
    
    Owner_Name         sid 
      ------------------ -----------------------------------------------
    NULL               0xDB79ED7B6731CF4E8DC7DF02871E3E36 
    
  13. Executa o testexec procedimento armazenado. Agora deve ver a mensagem de erro "15517".

    USE Demodb_15517 
    GO 
    EXEC dbo.testexec 
    GO
    
    Msg 15517, Level 16, State 1, Procedure dbo.testexec, Line 0 [Batch Start Line 19] 
    Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission. 
    
  14. Para resolver o erro, altere o dbo para um utilizador válido (login2) usando o seguinte comando:

    ALTER AUTHORIZATION ON DATABASE:: Demodb_15517 TO [login2]   
    
  15. Execute novamente a Query 2 e verifique se os utilizadores DBO agora resolvem para o utilizador login2.

    Owner_Name          SID
    ---------------------------------------------------------------- 
    login2              0xD63086DD7277BC4EB88013D359AF73A6 
    
  16. Tente novamente executar o procedimento armazenado de teste. Repare que agora corre com sucesso.

    USE Demodb_15517 
    GO 
    EXEC dbo.testexec 
    GO
    
    /* -- You get an output that resembles the following 
    ---------------------------------------------------------------------------------------------------------
    Microsoft SQL Server 2019 (RTM-CU16-GDR) (KB5014353) - 15.0.4236.7 (X64)  
    May 29 2022 15:55:47  
    Copyright (C) 2019 Microsoft Corporation 
    Express Edition (64-bit) on Windows 10 Enterprise 10.0 <X64> (Build 22621: ) (Hypervisor) 
    */