首页 > 解决方案 > SQL Server - 查找服务器上所有数据库的用户/登录名的所有权限/访问权限

问题描述

案子:

背景:

所需的修改:

我不知道如何查看服务器上的所有数据库。

            DECLARE @DatabaseUserName VARCHAR(50)  -- ='user'
          , @LoginName        VARCHAR(50)  -- ='login'



    SELECT      [UserType]         = CASE princ.[type] WHEN 'S' THEN 'SQL User'
                                         WHEN 'U' THEN 'Windows User'
                                         WHEN 'G' THEN 'Windows Group' END
              , [DatabaseUserName] = princ.[name]
              , [LoginName]        = ulogin.[name]
              , [Role]             = NULL
              , [PermissionType]   = perm.[permission_name]
              , [PermissionState]  = perm.[state_desc]
              , [ObjectType]       = CASE perm.[class] WHEN 1 THEN obj.[type_desc] -- Schema-contained objects
                                         ELSE perm.[class_desc]                    -- Higher-level objects
                                     END
              , [Schema]           = objschem.[name]
              , [ObjectName]       = CASE perm.[class] WHEN 3 THEN permschem.[name] -- Schemas
                                         WHEN 4 THEN imp.[name]                     -- Impersonations
                                         ELSE OBJECT_NAME (perm.[major_id])         -- General objects
                                     END
              , [ColumnName]       = col.[name]
    FROM
        --Database user
                sys.database_principals  AS princ
    --Login accounts
    LEFT JOIN   sys.server_principals    AS ulogin ON ulogin.[sid] = princ.[sid]
    --Permissions
    LEFT JOIN   sys.database_permissions AS perm ON perm.[grantee_principal_id] = princ.[principal_id]
    LEFT JOIN   sys.schemas              AS permschem ON permschem.[schema_id] = perm.[major_id]
    LEFT JOIN   sys.objects              AS obj ON obj.[object_id] = perm.[major_id]
    LEFT JOIN   sys.schemas              AS objschem ON objschem.[schema_id] = obj.[schema_id]
    --Table columns
    LEFT JOIN   sys.columns              AS col ON col.[object_id] = perm.[major_id]
                                                   AND   col.[column_id] = perm.[minor_id]
    --Impersonations
    LEFT JOIN   sys.database_principals  AS imp ON imp.[principal_id] = perm.[major_id]
    WHERE       princ.[type] IN ( 'S', 'U', 'G' )
                -- No need for these system accounts
                AND princ.[name] NOT IN ( 'sys', 'INFORMATION_SCHEMA' )
                AND (princ.[name] = @DatabaseUserName OR  @DatabaseUserName IS NULL)            
                AND (ulogin.[name] = @LoginName OR  @LoginName IS NULL)
    UNION

    --2) List all access provisioned to a SQL user or Windows user/group through a database or application role
    SELECT      [UserType]         = CASE membprinc.[type] WHEN 'S' THEN 'SQL User'
                                         WHEN 'U' THEN 'Windows User'
                                         WHEN 'G' THEN 'Windows Group' END
              , [DatabaseUserName] = membprinc.[name]
              , [LoginName]        = ulogin.[name]
              , [Role]             = roleprinc.[name]
              , [PermissionType]   = perm.[permission_name]
              , [PermissionState]  = perm.[state_desc]
              , [ObjectType]       = CASE perm.[class] WHEN 1 THEN obj.[type_desc] -- Schema-contained objects
                                         ELSE perm.[class_desc]                    -- Higher-level objects
                                     END
              , [Schema]           = objschem.[name]
              , [ObjectName]       = CASE perm.[class] WHEN 3 THEN permschem.[name] -- Schemas
                                         WHEN 4 THEN imp.[name]                     -- Impersonations
                                         ELSE OBJECT_NAME (perm.[major_id])         -- General objects
                                     END
              , [ColumnName]       = col.[name]
    FROM
        --Role/member associations
                sys.database_role_members AS members
    --Roles
    JOIN        sys.database_principals   AS roleprinc ON roleprinc.[principal_id] = members.[role_principal_id]
    --Role members (database users)
    JOIN        sys.database_principals   AS membprinc ON membprinc.[principal_id] = members.[member_principal_id]
    --Login accounts
    LEFT JOIN   sys.server_principals     AS ulogin ON ulogin.[sid] = membprinc.[sid]
    --Permissions
    LEFT JOIN   sys.database_permissions  AS perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
    LEFT JOIN   sys.schemas               AS permschem ON permschem.[schema_id] = perm.[major_id]
    LEFT JOIN   sys.objects               AS obj ON obj.[object_id] = perm.[major_id]
    LEFT JOIN   sys.schemas               AS objschem ON objschem.[schema_id] = obj.[schema_id]
    --Table columns
    LEFT JOIN   sys.columns               AS col ON col.[object_id] = perm.[major_id]
                                                    AND   col.[column_id] = perm.[minor_id]
    --Impersonations
    LEFT JOIN   sys.database_principals   AS imp ON imp.[principal_id] = perm.[major_id]
    WHERE       membprinc.[type] IN ( 'S', 'U', 'G' )
                -- No need for these system accounts
                AND membprinc.[name] NOT IN ( 'sys', 'INFORMATION_SCHEMA' )
                AND (membprinc.[name] = @DatabaseUserName OR  @DatabaseUserName IS NULL)
                AND (ulogin.[name] = @LoginName OR  @LoginName IS NULL)
    UNION

    --3) List all access provisioned to the public role, which everyone gets by default
    SELECT      [UserType]         = '{All Users}'
              , [DatabaseUserName] = '{All Users}'
              , [LoginName]        = '{All Users}'
              , [Role]             = roleprinc.[name]
              , [PermissionType]   = perm.[permission_name]
              , [PermissionState]  = perm.[state_desc]
              , [ObjectType]       = CASE perm.[class] WHEN 1 THEN obj.[type_desc] -- Schema-contained objects
                                         ELSE perm.[class_desc]                    -- Higher-level objects
                                     END
              , [Schema]           = objschem.[name]
              , [ObjectName]       = CASE perm.[class] WHEN 3 THEN permschem.[name] -- Schemas
                                         WHEN 4 THEN imp.[name]                     -- Impersonations
                                         ELSE OBJECT_NAME (perm.[major_id])         -- General objects
                                     END
              , [ColumnName]       = col.[name]
    FROM
        --Roles
                sys.database_principals  AS roleprinc
    --Role permissions
    LEFT JOIN   sys.database_permissions AS perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
    LEFT JOIN   sys.schemas              AS permschem ON permschem.[schema_id] = perm.[major_id]
    --All objects
    JOIN        sys.objects              AS obj ON obj.[object_id] = perm.[major_id]
    LEFT JOIN   sys.schemas              AS objschem ON objschem.[schema_id] = obj.[schema_id]
    --Table columns
    LEFT JOIN   sys.columns              AS col ON col.[object_id] = perm.[major_id]
                                                   AND   col.[column_id] = perm.[minor_id]
    --Impersonations
    LEFT JOIN   sys.database_principals  AS imp ON imp.[principal_id] = perm.[major_id]
    WHERE       roleprinc.[type] = 'R'
                AND roleprinc.[name] = 'public'
                AND obj.[is_ms_shipped] = 0
                AND (roleprinc.[name] = @DatabaseUserName OR  @DatabaseUserName IS NULL)


    ORDER BY    [UserType]
              , [DatabaseUserName]
              , [LoginName]
              , [Role]
              , [Schema]
              , [ObjectName]
              , [ColumnName]
              , [PermissionType]
              , [PermissionState]
              , [ObjectType];

标签: sql-server

解决方案


我可以想到两种方法可以实现这一目标。

第一种方法是使用临时表并对所有数据库执行权限脚本,如下所示:

DECLARE @DatabaseName VARCHAR(50);
DECLARE @SqlCommand NVARCHAR(MAX);
DECLARE @DatabaseUserName VARCHAR(50); -- ='user'
DECLARE @LoginName VARCHAR(50); -- ='login'

CREATE TABLE #TEMP_OVERVIEW
(
  DatabaseName     VARCHAR(128)  NOT NULL
, UserType         VARCHAR(13)   NULL
, DatabaseUserName NVARCHAR(128) NOT NULL
, LoginName        NVARCHAR(128) NULL
, Role             NVARCHAR(128) NULL
, PermissionType   NVARCHAR(128) NULL
, PermissionState  NVARCHAR(60)  NULL
, ObjectType       NVARCHAR(60)  NULL
, [Schema]         sys.sysname   NULL
, ObjectName       NVARCHAR(128) NULL
, ColumnName       sys.sysname   NULL
);

DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT
      name
FROM  master.sys.databases
WHERE name NOT IN ('master', 'msdb', 'model', 'tempdb')
      AND state_desc = 'online';

OPEN db_cursor;

FETCH NEXT FROM db_cursor
INTO
  @DatabaseName;

WHILE @@FETCH_STATUS = 0
BEGIN
  SELECT
    @SqlCommand = N'USE ' + @DatabaseName + N';' + N'
INSERT INTO #TEMP_OVERVIEW
SELECT '''        + @DatabaseName + N''', t.*
FROM (

...在此处插入您的脚本...

) AS t
' ;

  EXEC sp_executesql @SqlCommand;

  FETCH NEXT FROM db_cursor
  INTO
    @DatabaseName;
END;

CLOSE db_cursor;
DEALLOCATE db_cursor;

SELECT
      *
FROM  #TEMP_OVERVIEW
WHERE DatabaseUserName = @DatabaseUserName
      AND LoginName = @LoginName;

DROP TABLE #TEMP_OVERVIEW;

第二种方法是使用sp_MSforeachdb. 但在进一步解释这一点之前,我必须提醒您,因为它是一个全局游标,并且多年来被微软认为已弃用。它也是无证的/不受支持的,所以如果你用 搞砸了一些东西sp_MSforeachdb,你就靠自己了。例如,使用:

EXEC sp_MSforeachdb 'USE ?; SELECT ''?'' AS DATABASE_NAME, * FROM INFORMATION_SCHEMA.TABLES'

这会给你:

在此处输入图像描述

以此类推,适用于您服务器上的所有数据库,因此您可以看到很可能将您的权限脚本合并到sp_MSforeachdb调用中。


推荐阅读