2013-08-12 18 views
9

Szukam instrukcji select, która pobierze listę wszystkich ról bazy danych dla bieżącego połączenia.Jak sprawdzać role bieżącego użytkownika

Chcę utworzyć widok, który zwróci wszystkie role do oprogramowania klienckiego, tak że oprogramowanie może dostosować swój interfejs użytkownika według ról (np pokazać/ukryć pozycji menu itp)

Odpowiedz

17

nie należy używać nieaktualnych zacofane poglądy zgodności (search this page for sysusers, for example). Zamiast tego powinieneś używać sys.database_principals i sys.database_role_members. Należy pamiętać, że bieżące połączenie mogło uzyskać dostęp poza zakresem bazy danych (np. Zwróci puste wyniki, jeśli użytkownik jest sysadmin, w którym to przypadku nie musi być jawnie przyznane członkostwo roli lub uprawnienia). Również dla uprawnień przypisanych jawnie poza zakresem roli, które zastąpią te udostępnione przez rolę, należy dodatkowo sprawdzić numer sys.database_permissions. Oto samodzielny przykład, który możesz sprawdzić (o ile nie masz jeszcze loginu o nazwie blatfarA lub bazy danych o nazwie floob).

CREATE LOGIN blatfarA WITH PASSWORD = 'foo', CHECK_POLICY = OFF; 
GO 
CREATE DATABASE floob; 
GO 
USE floob; 
GO 
CREATE USER blatfarB FROM LOGIN [blatfarA] WITH DEFAULT_SCHEMA = dbo; 
GO 
GRANT SELECT, UPDATE ON SCHEMA::dbo TO blatfarB; 
DENY INSERT, EXECUTE ON SCHEMA::dbo TO blatfarB; 
GO 
EXEC sp_addrolemember N'db_datareader', N'blatfarB' 
GO 

Aby przetestować go:

EXECUTE AS LOGIN = N'blatfarA'; 
GO 

DECLARE @login NVARCHAR(256), @user NVARCHAR(256); 

SELECT @login = login_name FROM sys.dm_exec_sessions WHERE session_id = @@SPID; 

SELECT @user = d.name 
    FROM sys.database_principals AS d 
    INNER JOIN sys.server_principals AS s 
    ON d.sid = s.sid 
    WHERE s.name = @login; 

SELECT u.name, r.name 
    FROM sys.database_role_members AS m 
    INNER JOIN sys.database_principals AS r 
    ON m.role_principal_id = r.principal_id 
    INNER JOIN sys.database_principals AS u 
    ON u.principal_id = m.member_principal_id 
    WHERE u.name = @user; 

SELECT class_desc, major_id, permission_name, state_desc 
    FROM sys.database_permissions 
    WHERE grantee_principal_id = USER_ID(@user); 

GO 
REVERT; 

Wyniki:

name  name 
-------- ------------- 
blatfarB db_datareader 

class_desc major_id permission_name state_desc 
---------- -------- --------------- ---------- 
DATABASE 0   CONNECT   GRANT 
SCHEMA  1   INSERT   DENY 
SCHEMA  1   EXECUTE   DENY 
SCHEMA  1   SELECT   GRANT 
SCHEMA  1   UPDATE   GRANT 

oczyścić:

USE master; 
GO 
ALTER DATABASE floob SET SINGLE_USER WITH ROLLBACK IMMEDIATE; 
GO 
DROP DATABASE floob; 
GO 
DROP LOGIN blatfarA; 
GO 
+0

Hej dzięki, to jest o wiele lepsze. Tymczasem okazało się, że moja pierwsza próba nie zawsze przyniosła poprawne wyniki. Zmieniłem zaakceptowaną odpowiedź. –

+1

Prawdopodobnie można uprościć kod w wersji demonstracyjnej, aby użyć 'CURRENT_USER' zamiast zawracać sobie głowę przy zapytaniu' @ login'. Stare zwyczaje umierają ciężko. –

+0

"Stare nawyki umierają" - masz rację !! –

5

oto gdzie można start:

select u.name, g.name 
from sysmembers as m 
    inner join sys.sysusers u on u.[uid] = m.memberuid 
    inner join sys.sysusers g on g.[uid] = m.groupuid 
+2

Dlaczego używasz nieaktualne widoki ze zgodnością, które zostaną usunięte w przyszłej wersja SQL Server? (Wyszukaj [tej stronie] (http://technet.microsoft.com/en-us/library/bb510662 (v = sql.100) .aspx) dla 'sysusers'.) –

+0

Ponadto, nie widzę, jak to odpowiedzi "Chcę poznać wszystkie ROLKI DATABASE, które zostały przypisane do mojego bieżącego połączenia." To zwraca wszystko. –

Powiązane problemy