단일보기에 액세스 할 수있는 사용자를 추가하는 방법은 무엇입니까?


14

MSSQL Server Management Studio 2008과 함께 작업하고 있으며 데이터 조정을 위해 타사에 뷰를 노출해야합니다. 적절한보기를 만들었지 만 사용자를 만드는 데 문제가 있으며 해당 사용자에게보기에서 선택할 수있는 적절한 권한을 부여합니다.

나는 로그인과 사용자를 생성하기 위해 마법사를 따랐다. 그리고 Securables 섹션에서 그랜트 박스가 선택된 상태로 내 뷰를 추가했다. 모든 것이 괜찮아 보였지만 그 사용자로 로그인하여 "Select * from MyViewName"을 시도했을 때 선택 권한이 거부되었다고 알려줍니다.

난 단지 (단지 대신 마법사의 SQL을 사용하여이 시간) 사용자를 다시 명시 적으로 선택 권한을 부여하고 지금은 나에게 오류를주고있다 : Msg 916, Level 14, State 1, Line 2 The server principal "username" is not able to access the database "unrelated_db" under the current security context.(나는 관련이없는 데이터베이스에 액세스하려고 이유를 알고하지 않습니다 ...)

나는 여기서 어디로 가야할지 모르겠다. 다시 기본적으로 필요한 것은 제 3 자에게 데이터베이스에 연결 하고이보기에서 선택할 수 있도록 사용자에게 제공하는 것입니다.


3
뷰가 다른 데이터베이스의 기본 테이블을 참조합니까? 그렇다면 소유권 체인을 처리해야합니다. 또한 현재 데이터베이스 컨텍스트가 원하는 데이터베이스로 설정되어 있는지 확인하십시오.
Thomas Stringer

뷰의 종속성을 볼 수있는 방법이 있습니까? 내가 아는 한,보기의 모든 것이 기본 데이터베이스에 포함 되어야 합니다. 보기는 세 개의 필드로, 두 개는 지불 세부 사항 테이블에서오고 다른 하나는 계정 세부 사항 테이블로옵니다. 그러나 두 테이블은 모두 동일한 데이터베이스 (및보기와 동일한 데이터베이스)에 있습니다.
velojason

답변:


16

이를 위해 UI를 사용하지 마십시오. 혼란스러운 혼란입니다.

하나의보기에서 선택할 권한이있는 특정 로그인에 대해 데이터베이스에 사용자를 만드는 것이 원하는 것처럼 들립니다. 따라서 이미 로그인이 생성되었으므로

USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO

여기 편집 은 언급 한 오류로 이어질 스크립트의 예입니다.

먼저 unrelated_db에 테이블을 작성하십시오.

CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO

이제 상대적으로 제한된 로그인을 만듭니다.

USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO

이제 뷰가 ​​위치 할 데이터베이스를 작성하고 로그인을 사용자로 추가하십시오.

CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO

이제 다른 데이터베이스의 테이블을 참조하고 다른 테이블과 동의어를 작성하는 함수를 작성하십시오.

CREATE FUNCTION dbo.checkbar()
RETURNS INT
AS 
BEGIN
    RETURN 
    (
      SELECT TOP (1) bar 
        FROM unrelated_db.dbo.foo 
        ORDER BY bar
    );
END
GO
CREATE SYNONYM dbo.foo FOR unrelated_db.dbo.foo;
GO

이제 로컬 테이블을 만듭니다.

CREATE TABLE dbo.PaymentDetails
(
  PaymentID INT
);
GO

이제 테이블, 함수 및 동의어를 참조하는 뷰를 작성하고 다음을 부여 SELECT하십시오 username.

CREATE VIEW dbo.SomeView
AS
  SELECT 
    p.PaymentID, 
    x = dbo.checkbar(), -- function that pulls from other DB
    y = (SELECT bar FROM dbo.foo) -- synonym to other DB
    FROM dbo.PaymentDetails AS p;
GO
GRANT SELECT ON dbo.SomeView TO username;
GO

이제 as를 실행 username하고 뷰에서 로컬 열만 선택하십시오.

EXECUTE AS USER = 'username';
GO
  -- even though I don't reference any of the columns 
  -- in the other DB, I am denied SELECT on the view:
SELECT PaymentID FROM dbo.SomeView;
GO
REVERT;
GO

결과:

메시지 916, 수준 14, 상태 1, 줄 3
서버 보안 주체 "username"은 현재 보안 컨텍스트에서 "unrelated_db"데이터베이스에 액세스 할 수 없습니다.

이제 외부 객체를 참조하지 않도록 뷰를 변경하고 위를 SELECT다시 실행하면 작동합니다.

ALTER VIEW dbo.SomeView
AS
  SELECT 
    p.PaymentID 
    --x = dbo.checkbar(),
    --y = (SELECT bar FROM dbo.foo)
    FROM dbo.PaymentDetails AS p;
GO

지불 세부 사항, 계정 세부 사항 및 MyView 오브젝트에 대한 스크립트를 보여주지 않으면이 쿼리가 결과를 리턴하는지 알려주십시오. 카탈로그 뷰를 통해 다양한 객체에 대한 참조를 찾을 수 sys.sql_expression_dependencies있지만이 뷰는 완벽하지 않습니다. 뷰가 새로 고쳐지는 모든 뷰 (예 : 뷰가 다른 뷰를 참조하거나 기본 스키마가 변경된 경우)에 따라 달라집니다. 정확합니다.

DECLARE 
  @dbname   SYSNAME = N'unrelated_db',
  @viewname SYSNAME = N'dbo.SomeView';

SELECT DISTINCT 
    [This object] = 
    OBJECT_SCHEMA_NAME([referencing_id]) 
      + '.' + OBJECT_NAME([referencing_id]), 
    [references this object] = 
    OBJECT_SCHEMA_NAME([referenced_id]) 
      + '.' + OBJECT_NAME([referenced_id]), 
    [and touches this database] = referenced_database_name,
    [and is a(n)] = o.type_desc,
    [if synonym, it references] = s.base_object_name
FROM sys.sql_expression_dependencies AS d
LEFT OUTER JOIN sys.objects AS o
ON o.[object_id] = d.referenced_id
LEFT OUTER JOIN sys.synonyms AS s
ON d.referenced_id = s.[object_id]
AND s.base_object_name LIKE '%[' + @dbname + ']%'
WHERE OBJECT_ID(@viewname) IN (
        referenced_id, 
        referencing_id, 
        (SELECT referencing_id FROM sys.sql_expression_dependencies 
        WHERE referenced_database_name = @dbname)
) OR referenced_database_name = @dbname;

SQL Server는 단순히 unrelated_db재미를 위해 액세스하려고 시도하지 않습니다 ... 사용하려는보기에서 해당 데이터베이스와 연결되어 있어야합니다. 불행히도 뷰 정의와 해당 객체에 대한 자세한 내용을 볼 수 없다면 추측 할 수 있습니다. 내가 생각할 수있는 두 가지 주요 사항은 세 부분으로 된 이름을 사용하는 동의어 또는 함수이지만 실제 스크립트를 보면 추측하는 대신 훨씬 더 나은 아이디어를 얻을 수 있습니다. :-)

당신은 또한 확인하고 싶을 수도 sys.dm_sql_referenced_entities있지만,이 함수는 위 예제에서 유용한 것을 반환하지 않습니다.


6
create login YourTpvLogin with password = 'enter new password here'
go

use SomeDb
go

create user YourTpvUser for login YourTpvLogin
go

grant select on YourView to YourTpvUser
go

다음을 수행하여이를 테스트 할 수 있습니다.

execute as user = 'YourTpvUser'
go

select *
from YourView

revert
go

분명히 이것은 재귀 적으로 권한을 부여하지 않습니다. 사용자는 "YourView"에서 선택할 수 있지만 "YourView"가 다른 관계 / 데이터베이스에 의존하는 경우 실패합니다. 서버 보안 "YourTpvUser"가 현재 보안 컨텍스트에서 "OtherDb"데이터베이스에 액세스 할 수 없습니다.
lilalinux
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.