MSSQLSERVER_15517

Dotyczy:SQL Server

Szczegóły

Attribute Value
Nazwa produktu SQL Server
Identyfikator zdarzenia 15517
Źródło zdarzenia MSSQLSERVER
Składnik SQLEngine
Nazwa symboliczna SEC_CANNOTEXECUTEASUSER
Tekst wiadomości Nie można wykonać jako principal bazy danych, ponieważ principal "principal" nie istnieje, tego typu principal nie może być podszyty lub nie masz pozwolenia.

Explanation

Błąd ten zwykle występuje, ponieważ Microsoft SQL Server nie jest w stanie uzyskać informacji o kontekście wykonania zasady, które zostały określone w instrukcji użytkownika lub module, używając tego EXECUTE AS polecenia.

Identyfikator bezpieczeństwa danych logowania (SID) jest automatycznie zapisywany po utworzeniu bazy danych na instancji SQL Server jako właściciel bazy danych w odpowiadającym wierszu bazy danych w tabeli sys.databases oraz dla elementu dbo użytkownika w tabeli sys.database_principals w bazie danych.

Instrukcje lub moduły wykorzystujące klauzulę EXECUTE AS OWNER będą działać zgodnie z oczekiwaniami, jeśli wpis SID przechowywany dla użytkownika dbo jest poprawny.

Uwaga / Notatka

Problem może wystąpić przy każdym principalu użytym w instrukcji, EXECUTE AS który nie istnieje na serwerze, do którego baza danych jest przywracana.

Oto kilka typowych scenariuszy, które mogą powodować ten problem:

  • Przywracasz bazę danych na tym samym serwerze, gdzie pierwotnie wykonano kopię zapasową, ale zasada SQL Server, która stworzyła bazę danych, z jakiegoś powodu nie jest już ważna. Przykład:

    • Logowanie do uwierzytelniania SQL Server zostało usunięte.
    • Logowanie do Windows authentication nie jest już przeznaczone dla ważnego użytkownika w Active Directory, ponieważ pracownik opuścił firmę.
  • Przywracasz bazę danych na serwerze, która różni się od instancji, w której pierwotnie wykonano kopię zapasową, ale zasada SQL Server, która stworzyła bazę danych, nie jest ważną zasadą na nowym serwerze.

    • Jeśli użytkownik jest logowaniem do SQL Server, główny użytkownik może istnieć na docelowym lub docelowym serwerze, ale wartość sid będzie inna.
    • Jeśli użytkownik jest logowany przez Windows, logowanie do Windows nie istnieje na docelowym serwerze lub nie jest już ważne.

Użytkownik lub aplikacja uruchamiająca procedurę, funkcję lub wyzwalacz nie ma odpowiednich uprawnień, aby podszyć się pod główną osobę określoną w EXECUTE AS instrukcji.

Akcja użytkownika

Użyj nazwy istniejącego podmiotu lub przyznaj wymaganym użytkownikom pozwolenie IMPERSONATE na ten podmiot.

Aby rozwiązać problem wynikający z nieprawidłowego błędu użytkownika dbo, zmień dbo_User wartość na ważny login na serwerze, uruchamiając następujące polecenie:

ALTER AUTHORIZATION ON DATABASE:: DBName TO [NewLogin]  

Przykładowy scenariusz

  1. Stwórz dwa tymczasowe zasady:

    CREATE LOGIN login1 WITH PASSWORD = 'J345#$)thb';
    CREATE LOGIN login2 WITH PASSWORD = 'Uor80$23b';
    
  2. Dodaj te logowania do roli administratora systemu (tylko dla demonstracji).

  3. Zaloguj się do swojej instancji SQL Server, używając login1.

  4. Stwórz demonstracyjną bazę danych oraz procedurę przechowywaną, która zostanie testexec nazwana, uruchamiając następujący skrypt:

    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. Uruchom następujące zapytania i sprawdź, czy wartości sid rozwiązują się z poprawnym logowaniem:

    • Zapytanie 1: Sprawdź wartość Owner_Name wartości w 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
      
    • Zapytanie 2: Sprawdź Owner_Name wartość w tabeli sys.database_principals w bazie demonstracyjnej:

      SELECT SUSER_SNAME(sid) AS Owner_Name, sid 
      FROM Demodb_15517.sys.database_principals 
      WHERE NAME = N'dbo'; 
      
      Owner_Name    SID
      ------------- ------------------------------------------------ 
      login1        0xDB79ED7B6731CF4E8DC7DF02871E3E36
      
  6. Zrób kopię zapasową bazy demonstracyjnej, używając zapytania przypominającego następujący skrypt:

    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. Usuń bazę danych demonstracyjnych i login1:

    DROP DATABASE demodb_15517
    GO
    DROP login login1
    GO
    
  8. Zaloguj się do SQL Server jako .login2

  9. Przywróć demonstracyjną bazę danych z kopii zapasowej, używając instrukcji przypominającej następujący skrypt:

    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. Ponownie uruchom zapytanie 1 i zapytanie 2.

  11. W Zapytaniu 1 sprawdź wartość Owner_Name wartości w sys.databases. Wartość teraz odzwierciedla 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. W Zapytaniu 2 sprawdź wartość wartości Owner_Name w tabeli sys.database_principals w bazie demonstracyjnej. Wartość teraz odzwierciedla 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. Uruchom procedurę zapisaną testexec . Teraz powinieneś zobaczyć komunikat o błędzie "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. Aby rozwiązać błąd, zmień dbo na poprawnego użytkownika (login2) za pomocą następującego polecenia:

    ALTER AUTHORIZATION ON DATABASE:: Demodb_15517 TO [login2]   
    
  15. Ponownie uruchom zapytanie 2 i sprawdź, czy użytkownicy DBO teraz decydują się na użytkownika login2.

    Owner_Name          SID
    ---------------------------------------------------------------- 
    login2              0xD63086DD7277BC4EB88013D359AF73A6 
    
  16. Spróbuj ponownie, aby uruchomić procedurę testową przechowywaną. Zauważ, że teraz działa pomyślnie.

    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) 
    */