วิธีการโคลนผู้ใช้ใน SQL Server 2008 R2


23

มีวิธีการโคลนการรักษาความปลอดภัยของผู้ใช้และการอนุญาตใน Microsoft SQL Server โดยเฉพาะอย่างยิ่งการใช้ SQL Server Management Studio GUI หรือไม่

คำตอบ:


38

หมายเหตุ: สคริปต์ด้านล่างไม่ได้ตั้งค่าสิทธิ์ใด ๆ เลยเพียงแค่สร้างสคริปต์ที่สามารถคัดลอกและวางไปยังแบบสอบถามใหม่ซึ่งสามารถแก้ไขได้ก่อนดำเนินการ

สคริปต์ด้านล่างจะช่วยให้คุณคัดลอก / คัดลอกการอนุญาตของผู้ใช้รายหนึ่งไปยังอีกคนหนึ่ง:

--- To copy permissions of one user/role to another user/role.

USE database_name -- Use the database from which you want to extract the permissions
GO


SET NOCOUNT ON
DECLARE @OldUser sysname, @NewUser sysname

SET @OldUser = 'userOLD' --The user or role from which to copy the permissions from
SET @NewUser = 'userNEW'  --The user or role to which to copy the permissions to


SELECT  'USE' + SPACE(1) + QUOTENAME(DB_NAME()) AS '--Database Context'


SELECT  '--Cloning permissions from' + SPACE(1) + QUOTENAME(@OldUser) + SPACE(1) + 'to' + SPACE(1) + QUOTENAME(@NewUser) AS '--Comment'


SELECT  'EXEC sp_addrolemember @rolename ='
    + SPACE(1) + QUOTENAME(USER_NAME(rm.role_principal_id), '''') + ', @membername =' + SPACE(1) + QUOTENAME(@NewUser, '''') AS '--Role Memberships'
FROM    sys.database_role_members AS rm
WHERE   USER_NAME(rm.member_principal_id) = @OldUser
ORDER BY rm.role_principal_id ASC


SELECT  CASE WHEN perm.state <> 'W' THEN perm.state_desc ELSE 'GRANT' END
    + SPACE(1) + perm.permission_name + SPACE(1) + 'ON ' + QUOTENAME(SCHEMA_NAME(obj.schema_id)) + '.' + QUOTENAME(obj.name)
    + CASE WHEN cl.column_id IS NULL THEN SPACE(0) ELSE '(' + QUOTENAME(cl.name) + ')' END
    + SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
    + CASE WHEN perm.state <> 'W' THEN SPACE(0) ELSE SPACE(1) + 'WITH GRANT OPTION' END AS '--Object Level Permissions'
FROM    sys.database_permissions AS perm
    INNER JOIN
    sys.objects AS obj
    ON perm.major_id = obj.[object_id]
    INNER JOIN
    sys.database_principals AS usr
    ON perm.grantee_principal_id = usr.principal_id
    LEFT JOIN
    sys.columns AS cl
    ON cl.column_id = perm.minor_id AND cl.[object_id] = perm.major_id
WHERE   usr.name = @OldUser
ORDER BY perm.permission_name ASC, perm.state_desc ASC


SELECT  CASE WHEN perm.state <> 'W' THEN perm.state_desc ELSE 'GRANT' END
    + SPACE(1) + perm.permission_name + SPACE(1)
    + SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
    + CASE WHEN perm.state <> 'W' THEN SPACE(0) ELSE SPACE(1) + 'WITH GRANT OPTION' END AS '--Database Level Permissions'
FROM    sys.database_permissions AS perm
    INNER JOIN
    sys.database_principals AS usr
    ON perm.grantee_principal_id = usr.principal_id
WHERE   usr.name = @OldUser
AND perm.major_id = 0
ORDER BY perm.permission_name ASC, perm.state_desc ASC

12
@sweetritz หากมี GUI สำหรับการโคลนผู้ใช้คุณไม่จำเป็นต้องถามคำถามเพราะคุณสามารถกดปุ่มได้ ไม่มี เพียงเพราะคุณ "ไม่เก่งรหัส" ไม่ใช่ข้ออ้างที่จะไม่เรียนรู้ที่จะดีกว่า ...
Aaron Bertrand

6
อย่าทำให้ตัวเองถูก จำกัด เพียงแค่ใช้ GUI GUI นั้นเหมาะสำหรับมือใหม่ แต่มีข้อ จำกัด สำหรับงานของคุณสคริปต์ข้างต้นก็จะสร้างสคริปต์ที่แท้จริงที่คุณสามารถใช้เพื่อสร้างผู้ใช้ / โคลน
Kin Shah

1
ขอบคุณ Aaron สำหรับคำแนะนำ :) และ @Kin ขอบคุณสำหรับความช่วยเหลือนั่นเป็นการตอบกลับอย่างรวดเร็วจริง ๆ ชื่นชมมาก :) :)
sweetritz

2
ฉันคิดว่ามันต้องมีความชัดเจนว่าการเรียกใช้สคริปต์ด้านบนไม่ได้กำหนดสิทธิ์ให้กับอะไรเลยเพียงแค่สร้างสคริปต์ที่สามารถคัดลอกและวางลงในคิวรีใหม่ซึ่งสามารถแก้ไขได้ก่อนที่จะถูกดำเนินการ ฉันใช้มันเองและมันก็ทำงานได้อย่างสมบูรณ์แบบ! ประหยัดเวลาได้อย่างยอดเยี่ยม !!
อลันฟิชเชอร์

2
@ AlanFisher ขอบคุณสำหรับความคิดเห็นของคุณและดีใจที่ได้ช่วยเหลือคุณ อัปเดตคำตอบของฉันเพื่อสะท้อนความคิดเห็นของคุณ ขอบคุณมาก!
Kin Shah

3

นี่เป็นสคริปต์ที่ดีมากโดย Pavel Pawlowski ในการทำงาน: http://www.pawlowski.cz/2011/03/cloning-user-rights-database/

ข้อได้เปรียบหลัก:

  • สคริปต์ / คัดลอกการเป็นสมาชิกบทบาท
  • สคริปต์ / คัดลอกสิทธิ์ระดับวัตถุ
  • สคริปต์ / คัดลอกสิทธิ์ระดับฐานข้อมูล

ฉันไม่ใช่ผู้เขียนสคริปต์นี้ สคริปต์นี้คัดลอกมาจากลิงก์นี้ในบล็อกของ Pavel Pawlowski ดูลิงก์สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้สคริปต์

USE [master]
GO
--============================================
-- Author:      Pavel Pawlowski
-- Created:     2010/04/16
-- Description: Copies rights of old user to new user
--==================================================
CREATE PROCEDURE sp_CloneRights (
    @oldUser sysname, --Old user from which to copy right
    @newUser sysname, --New user to which copy rights
    @printOnly bit = 1, --When 1 then only script is printed on screen, when 0 then also script is executed, when NULL, script is only executed and not printed
    @NewLoginName sysname = NULL --When a NewLogin name is provided also a creation of user is part of the final script
)
AS
BEGIN
    SET NOCOUNT ON

    CREATE TABLE #output (
        command nvarchar(4000)
    )

    DECLARE
        @command nvarchar(4000),
        @sql nvarchar(max),
        @dbName nvarchar(128),
        @msg nvarchar(max)

    SELECT
        @sql = N'',
        @dbName = QUOTENAME(DB_NAME())

    IF (NOT EXISTS(SELECT 1 FROM sys.database_principals where name = @oldUser))
    BEGIN
        SET @msg = 'Source user ' + QUOTENAME(@oldUser) + ' doesn''t exists in database ' + @dbName
        RAISERROR(@msg, 11,1)
        RETURN
    END   

    INSERT INTO #output(command)
    SELECT '--Database Context' AS command UNION ALL
    SELECT    'USE' + SPACE(1) + @dbName UNION ALL
    SELECT 'SET XACT_ABORT ON'

    IF (ISNULL(@NewLoginName, '') <> '')
    BEGIN       
        SET @sql = N'USE ' + @dbName + N';
        IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = @newUser)
        BEGIN
            INSERT INTO #output(command)
            SELECT ''--Create user'' AS command

            INSERT INTO #output(command)
            SELECT 
                ''CREATE USER '' + QUOTENAME(@NewUser) + '' FOR LOGIN '' + QUOTENAME(@NewLoginName) +
                    CASE WHEN ISNULL(default_schema_name, '''') <> '''' THEN '' WITH DEFAULT_SCHEMA = '' + QUOTENAME(dp.default_schema_name)
                        ELSE ''''
                    END AS Command
            FROM sys.database_principals dp
            INNER JOIN sys.server_principals sp ON dp.sid = sp.sid
            WHERE dp.name = @OldUser
        END'

        EXEC sp_executesql @sql, N'@OldUser sysname, @NewUser sysname, @NewLoginName sysname', @OldUser = @OldUser, @NewUser = @NewUser, @NewLoginName=@NewLoginName
    END

    INSERT INTO #output(command)
    SELECT    '--Cloning permissions from' + SPACE(1) + QUOTENAME(@OldUser) + SPACE(1) + 'to' + SPACE(1) + QUOTENAME(@NewUser)


    INSERT INTO #output(command)
    SELECT '--Role Memberships' AS command

    SET @sql = N'USE ' + @dbName + N';
    INSERT INTO #output(command)
    SELECT ''EXEC sp_addrolemember @rolename ='' 
        + SPACE(1) + QUOTENAME(USER_NAME(rm.role_principal_id), '''''''') + '', @membername ='' + SPACE(1) + QUOTENAME(@NewUser, '''''''') AS command
    FROM    sys.database_role_members AS rm
    WHERE    USER_NAME(rm.member_principal_id) = @OldUser
    ORDER BY rm.role_principal_id ASC'

    EXEC sp_executesql @sql, N'@OldUser sysname, @NewUser sysname', @OldUser = @OldUser, @NewUser = @NewUser


    INSERT INTO #output(command)
    SELECT '--Object Level Permissions'

    SET @sql = N'USE ' + @dbName + N';
    INSERT INTO #output(command)
    SELECT    CASE WHEN perm.state <> ''W'' THEN perm.state_desc ELSE ''GRANT'' END
        + SPACE(1) + perm.permission_name + SPACE(1) + ''ON '' + QUOTENAME(USER_NAME(obj.schema_id)) + ''.'' + QUOTENAME(obj.name) 
        + CASE WHEN cl.column_id IS NULL THEN SPACE(0) ELSE ''('' + QUOTENAME(cl.name) + '')'' END
        + SPACE(1) + ''TO'' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
        + CASE WHEN perm.state <> ''W'' THEN SPACE(0) ELSE SPACE(1) + ''WITH GRANT OPTION'' END
    FROM    sys.database_permissions AS perm
        INNER JOIN
        sys.objects AS obj
        ON perm.major_id = obj.[object_id]
        INNER JOIN
        sys.database_principals AS usr
        ON perm.grantee_principal_id = usr.principal_id
        LEFT JOIN
        sys.columns AS cl
        ON cl.column_id = perm.minor_id AND cl.[object_id] = perm.major_id
    WHERE    usr.name = @OldUser
    ORDER BY perm.permission_name ASC, perm.state_desc ASC'

    EXEC sp_executesql @sql, N'@OldUser sysname, @NewUser sysname', @OldUser = @OldUser, @NewUser = @NewUser


    INSERT INTO #output(command)
    SELECT N'--Database Level Permissions'

    SET @sql = N'USE ' + @dbName + N';
    INSERT INTO #output(command)
    SELECT    CASE WHEN perm.state <> ''W'' THEN perm.state_desc ELSE ''GRANT'' END
        + SPACE(1) + perm.permission_name + SPACE(1)
        + SPACE(1) + ''TO'' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
        + CASE WHEN perm.state <> ''W'' THEN SPACE(0) ELSE SPACE(1) + ''WITH GRANT OPTION'' END
    FROM    sys.database_permissions AS perm
        INNER JOIN
        sys.database_principals AS usr
        ON perm.grantee_principal_id = usr.principal_id
    WHERE    usr.name = @OldUser
    AND    perm.major_id = 0
    ORDER BY perm.permission_name ASC, perm.state_desc ASC'

    EXEC sp_executesql @sql, N'@OldUser sysname, @NewUser sysname', @OldUser = @OldUser, @NewUser = @NewUser

    DECLARE cr CURSOR FOR
        SELECT command FROM #output

    OPEN cr

    FETCH NEXT FROM cr INTO @command

    SET @sql = ''

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF (@printOnly IS NOT NULL)
            PRINT @command

        SET @sql = @sql + @command + CHAR(13) + CHAR(10)
        FETCH NEXT FROM cr INTO @command
    END

    CLOSE cr
    DEALLOCATE cr

    IF (@printOnly IS NULL OR @printOnly = 0)
        EXEC (@sql)

    DROP TABLE #output
END
GO
EXECUTE sp_ms_marksystemobject 'dbo.sp_CloneRights'
GO

1
  1. คลิกขวาที่ฐานข้อมูลใน Object Explorer
  2. งาน -> สร้างสคริปต์ ...
  3. เลือกส่วนผู้ใช้เท่านั้นและเสร็จสิ้นตัวช่วยสร้างตามที่เป็นอยู่

ป้อนคำอธิบายรูปภาพที่นี่

หมายเหตุ: ในที่สุดคุณจะได้รับสคริปต์สำหรับการสร้างผู้ใช้ทั้งหมดและบทบาทของพวกเขาเกือบจะพร้อมแล้ว แต่สิ่งนี้จะไม่สร้างสคริปต์สำหรับการให้สิทธิ์ดำเนินการสำหรับกระบวนงานที่เก็บไว้แม้ว่าคุณจะเลือกสิทธิ์ระดับวัตถุสคริปต์เป็นจริง

ป้อนคำอธิบายรูปภาพที่นี่


1
มันไม่ทำงาน: มันจะไม่สร้างสคริปต์เพื่ออนุญาตการดำเนินการตามขั้นตอนการจัดเก็บ
สูงสุด

ใช่คุณถูก. ฉันได้เพิ่มความกระจ่างบางอย่าง
Iman Abidi

0

จากคำตอบที่ยอดเยี่ยมของ @ Kin-shah ฉันเขียนสคริปต์ที่สามารถคัดลอกการอนุญาตของฐานข้อมูลทั้งหมดในอินสแตนซ์ของเซิร์ฟเวอร์หนึ่ง sql มันอ่านได้แย่กว่ามาก แต่อาจมีประโยชน์ถ้าคุณมีผู้ใช้จำนวนมากและฐานข้อมูลจำนวนมาก:

USE master
GO

IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES r WHERE r.ROUTINE_NAME = 'clone_user')
DROP PROCEDURE clone_user
GO

CREATE PROCEDURE clone_user @database sysname, @OldUser sysname, @NewUser sysname AS BEGIN

DECLARE @sql nvarchar(max)
SET @sql = '

USE '+@database+'

DECLARE @database sysname = '''+@database+'''
DECLARE @OldUser sysname = '''+@OldUser+'''
DECLARE @NewUser sysname = '''+@NewUser+'''

SET NOCOUNT ON

SELECT  ''EXEC sp_addrolemember @rolename =''
    + SPACE(1) + QUOTENAME(USER_NAME(rm.role_principal_id), '''''''') + '', @membername ='' + SPACE(1) + QUOTENAME(@NewUser, '''''''') AS ''--Role Memberships''
INTO #roles
FROM    sys.database_role_members AS rm
WHERE   USER_NAME(rm.member_principal_id) = @OldUser
ORDER BY rm.role_principal_id ASC

SELECT  CASE WHEN perm.state <> ''W'' THEN perm.state_desc ELSE ''GRANT'' END
    + SPACE(1) + perm.permission_name + SPACE(1) + ''ON '' + QUOTENAME(USER_NAME(obj.schema_id)) + ''.'' + QUOTENAME(obj.name)
    + CASE WHEN cl.column_id IS NULL THEN SPACE(0) ELSE ''('' + QUOTENAME(cl.name) + '')'' END
    + SPACE(1) + ''TO'' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
    + CASE WHEN perm.state <> ''W'' THEN SPACE(0) ELSE SPACE(1) + ''WITH GRANT OPTION'' END AS ''--Object Level Permissions''
INTO #grant1
FROM    sys.database_permissions AS perm
    INNER JOIN
    sys.objects AS obj
    ON perm.major_id = obj.[object_id]
    INNER JOIN
    sys.database_principals AS usr
    ON perm.grantee_principal_id = usr.principal_id
    LEFT JOIN
    sys.columns AS cl
    ON cl.column_id = perm.minor_id AND cl.[object_id] = perm.major_id
WHERE   usr.name = @OldUser
ORDER BY perm.permission_name ASC, perm.state_desc ASC

SELECT  CASE WHEN perm.state <> ''W'' THEN perm.state_desc ELSE ''GRANT'' END
    + SPACE(1) + perm.permission_name + SPACE(1)
    + SPACE(1) + ''TO'' + SPACE(1) + QUOTENAME(@NewUser) COLLATE database_default
    + CASE WHEN perm.state <> ''W'' THEN SPACE(0) ELSE SPACE(1) + ''WITH GRANT OPTION'' END AS ''--Database Level Permissions''
INTO #grant2
FROM    sys.database_permissions AS perm
    INNER JOIN
    sys.database_principals AS usr
    ON perm.grantee_principal_id = usr.principal_id
WHERE   usr.name = @OldUser
AND perm.major_id = 0
ORDER BY perm.permission_name ASC, perm.state_desc ASC


IF EXISTS (SELECT * FROM #roles UNION ALL SELECT * FROM #grant1 UNION ALL SELECT * FROM #grant2) BEGIN
SELECT  ''USE ''+@database AS ''-- '+@database+'/'+@OldUser+''' INTO #tmp
SELECT * FROM #tmp UNION ALL SELECT * FROM #roles UNION ALL SELECT * FROM #grant1 UNION ALL SELECT * FROM #grant2
END

'

EXECUTE sp_executesql @sql

END

GO

EXEC sp_MSforeachdb 'EXECUTE [dbo].[clone_user] ?, ''OldUser'', ''NewUser'''

DROP PROCEDURE clone_user
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.