다음을 통해 공유


MSSQLSERVER_15517

적용 대상: SQL Server

세부 정보

attribute
제품 이름 SQL Server
이벤트 ID 15517
이벤트 원본 MSSQLSERVER
구성 요소 SQLEngine
심볼 이름 SEC_CANNOTEXECUTEASUSER
메시지 텍스트 보안 주체 "보안 주체"가 없거나, 이 유형의 보안 주체를 가장할 수 없거나, 권한이 없으므로 데이터베이스 보안 주체로 실행할 수 없습니다.

설명

이 오류는 일반적으로 Microsoft SQL Server가 문을 사용하여 EXECUTE AS 사용자 문 또는 모듈에 지정된 보안 주체의 실행 컨텍스트에 대한 정보를 가져올 수 없기 때문에 발생합니다.

SQL Server 인스턴스에서 데이터베이스를 테이블의 해당 데이터베이스 행 sys.databases 및 데이터베이스 내 테이블의 사용자 항목 sys.database_principals 에 대한 dbo 데이터베이스 소유자로 만들 때 로그인 정보 SID(보안 식별자)가 자동으로 저장됩니다.

dbo 사용자에 대해 저장된 SID 항목이 유효한 경우 절을 사용하는 EXECUTE AS OWNER 문 또는 모듈이 예상대로 작동합니다.

참고 항목

이 문제는 문에 EXECUTE AS 사용되고 데이터베이스가 복원되는 서버에 존재하지 않는 보안 주체에 대해 발생할 수 있습니다.

이 문제가 발생할 수 있는 몇 가지 일반적인 시나리오는 다음과 같습니다.

  • 백업이 원래 수행된 동일한 서버 인스턴스에서 데이터베이스를 복원하지만 데이터베이스를 만든 SQL Server 보안 주체는 어떤 이유로 더 이상 유효하지 않습니다. 예시:

    • SQL Server 인증 로그인이 제거되었습니다.
    • Windows 인증 로그인은 직원이 회사를 떠났기 때문에 Active Directory의 유효한 사용자에 대해 더 이상 사용할 수 없습니다.
  • 백업이 원래 수행된 인스턴스와 다른 서버의 데이터베이스를 복원하지만 데이터베이스를 만든 SQL Server 보안 주체는 새 서버에서 유효한 보안 주체가 아닙니다.

    • 사용자가 SQL Server 로그인인 경우 보안 주체가 대상 또는 대상 서버에 있을 수 있지만 값은 sid 다릅니다.
    • 사용자가 Windows 로그인인 경우 대상 서버에 Windows 로그인이 없거나 더 이상 유효하지 않습니다.

저장 프로시저, 함수 또는 트리거를 실행하는 사용자 또는 애플리케이션에는 문에 EXECUTE AS 지정된 보안 주체를 가장하는 데 필요한 권한이 없습니다.

사용자 작업

기존 보안 주체의 이름을 사용하거나 필요한 사용자에게 해당 보안 주체에 대한 IMPERSONATE 권한을 부여합니다.

잘못된 dbo 사용자 오류로 인해 발생하는 문제를 해결하려면 다음 명령을 실행하여 서버의 유효한 로그인으로 값을 변경 dbo_User 합니다.

ALTER AUTHORIZATION ON DATABASE:: DBName TO [NewLogin]  

예제 시나리오

  1. 두 개의 임시 보안 주체를 만듭니다.

    CREATE LOGIN login1 WITH PASSWORD = 'J345#$)thb';
    CREATE LOGIN login2 WITH PASSWORD = 'Uor80$23b';
    
  2. 이러한 로그인을 sysadmin 역할에 추가합니다(데모 전용).

  3. 를 사용하여 login1SQL Server 인스턴스에 로그인합니다.

  4. 다음 스크립트를 실행하여 명명 testexec 된 데모 데이터베이스 및 저장 프로시저를 만듭니다.

    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. 다음 쿼리를 실행하고 값이 sid 유효한 로그인으로 확인되는지 확인합니다.

    • 쿼리 1: sys.databases의 값 값을 Owner_Name 확인합니다.

      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
      
    • 쿼리 2: 데모 데이터베이스 내의 sys.database_principals 테이블 값을 확인 Owner_Name 합니다.

      SELECT SUSER_SNAME(sid) AS Owner_Name, sid 
      FROM Demodb_15517.sys.database_principals 
      WHERE NAME = N'dbo'; 
      
      Owner_Name    SID
      ------------- ------------------------------------------------ 
      login1        0xDB79ED7B6731CF4E8DC7DF02871E3E36
      
  6. 다음 스크립트와 유사한 쿼리를 사용하여 데모 데이터베이스를 백업합니다.

    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. 데모 데이터베이스를 삭제하고 login1다음을 수행합니다.

    DROP DATABASE demodb_15517
    GO
    DROP login login1
    GO
    
  8. 로 SQL Server login2에 로그인합니다.

  9. 다음 스크립트와 유사한 문을 사용하여 백업에서 데모 데이터베이스를 복원합니다.

    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. 쿼리 1 및 쿼리 2를 다시 실행합니다.

  11. 쿼리 1에서 값의 Owner_Name 값을 확인합니다 sys.databases. 이제 값이 반영됩니다.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. 쿼리 2에서 데모 데이터베이스 내의 Owner_Name sys.database_principals 테이블 값 값을 확인합니다. 이제 값이 반영됩니다.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. 저장 프로시저를 testexec 실행합니다. 이제 "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. 오류를 해결하려면 다음 명령을 사용하여 dbo를 유효한 사용자(login2)로 변경합니다.

    ALTER AUTHORIZATION ON DATABASE:: Demodb_15517 TO [login2]   
    
  15. 쿼리 2를 다시 실행하고 dbo 사용자가 이제 login2 사용자로 확인되는지 확인합니다.

    Owner_Name          SID
    ---------------------------------------------------------------- 
    login2              0xD63086DD7277BC4EB88013D359AF73A6 
    
  16. 다시 시도하여 테스트 저장 프로시저를 실행합니다. 이제 성공적으로 실행됩니다.

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

참고 항목

데이터베이스를 다른 서버에 복사

인스턴스 간에 로그인 및 암호 전송