SMO:在呼叫 TransferData() 時,登錄名已經有一個使用不同使用者名的帳戶
我需要實現以下要求。我已經設置了一個遠端 sql server express,某些使用者應該能夠在遠端伺服器上創建數據庫並分配其他使用者對其進行訪問(讀、寫)。使用者只能看到他們創建的或他們擁有權限的數據庫。
首先,我在遠端伺服器上創建了一個空數據庫=> dbo for new database is x,然後我創建了一個不同的登錄名:
USE [master] GO CREATE LOGIN [username] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]
然後拒絕查看任何數據庫:
USE master; GO DENY VIEW ANY DATABASE TO [username];
然後創建新使用者登錄:
USE dbName; CREATE USER [username] FOR LOGIN [username] ; GO
賦予數據庫所有者角色:
EXEC sp_addrolemember 'db_owner', [username]
授予查看數據庫的權限(這裡有點棘手,因為在 ssms 中它可以查看所有數據庫但它只能訪問映射的數據庫)
USE master GRANT VIEW ANY DATABASE TO [username];
現在在我給定的數據庫上,我有 2 個使用者,一個是使用者名,另一個是 dbo,它映射到創建數據庫的使用者上,並且與使用者名不同。
之後,我使用 SMO 將此數據庫從遠端伺服器傳輸到本地主機,並在執行時
transferDatabase.TransferData();
收到以下錯誤“登錄名已經有一個使用不同使用者名的帳戶。” 當我創建傳輸實例時,我還設置了屬性 CopyAllUsers=true。我怎樣才能解決這個問題?
我發現如果我進行以下更改
USE [master] GO CREATE LOGIN [username] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]
然後拒絕查看任何數據庫:
USE master; GO DENY VIEW ANY DATABASE TO [username]; USE master; GO ALTER AUTHORIZATION ON DATABASE::Dinesh TO [username]; GO
現在使用者名只能在 ssms 中看到映射的數據庫,並且傳輸可能會起作用。但是現在我無法區分數據庫的第一個創建者和最近授予的使用者。對於一個數據庫,我應該將 dbowner 權限授予多個使用者。
因此,如果我創建另一個登錄名並執行:
USE master; GO ALTER AUTHORIZATION ON DATABASE::dbName TO [anotherUser]; GO
現在使用者名無法訪問數據庫。
首先,如果你兩者都做:
GRANT VIEW ANY DATABASE TO [username];
和
DENY VIEW ANY DATABASE TO [username];
仍然獲勝,
DENY
因此授予它沒有意義,這也是每個新登錄的預設權限,因此無需再次授予它。
dbo
其次,您看不到數據庫主體和固定數據庫角色的任何成員之間的區別db_owner
。當您使某個使用者成為該使用者的成員時,db_owner
該使用者擁有該數據庫中所有可能的權限。但這與“在對象資源管理器中查看某些數據庫”這一事實無關。要“查看”OE 中的任何數據庫,登錄應該具有
view any database
權限。登錄而不是使用者。因此,您的登錄名可以沒有view any database
權限但仍然是db_owner
角色的成員,在這種情況下,使用者擁有該數據庫中的所有權限,但它無法“看到”OE 中的任何數據庫。
Dbo
database principal是一個特殊的principal,其中anysysadmin
(即sysadmin
伺服器角色的成員)被映射,並且database的OWNER也被映射到dbo。alter authorization
數據庫的所有者是創建此數據庫或通過執行語句分配為數據庫所有者的唯一一個登錄名:ALTER AUTHORIZATION ON DATABASE::Dinesh TO [username]
這樣,您將
LOGIN
使用者名分配為該數據庫的所有者。數據庫的所有者當然是db_owner
角色的成員,但反之則不然。DBO 將始終“看到”它在 OE 中擁有的數據庫sysadmin
。對於你的問題:
您收到的錯誤告訴您無法執行
CREATE USER [username] FOR LOGIN [username]
因為LOGIN使用者名已經映射到這個數據庫,如 dbo。因此,您無法將其重新映射到另一個使用者名。
如果您希望您的腳本執行沒有錯誤,請將數據庫所有者更改為任何其他登錄名,例如
sa
登錄名,這樣username
可以在此數據庫中創建登錄名。然後,如果您希望您的使用者名成為數據庫所有者,只需username
從該數據庫中刪除您的使用者並將授權更改為使用者名,這樣它將被映射到dbo
.或者,如果您已經知道您希望此使用者成為數據庫所有者,
username
請在傳輸之前從您的數據庫中刪除該使用者,並且它仍然存在於數據庫中,因為它映射到dbo
.因此,如果我創建另一個登錄名並執行:
使用大師;GO ALTER AUTHORIZATION ON DATABASE::dbName TO
$$ anotherUser $$; GO 現在使用者名無法訪問數據庫。
這是因為正如我上面解釋的,數據庫OWNER一次只能登錄一個。如果你想讓你的前任所有者訪問這個數據庫,你應該映射它:
USE dbName; CREATE USER [username] FOR LOGIN [username] ; GO
sysadmin
只有當它是或數據庫時,您才需要將登錄映射到數據庫owner
(我重複一遍,它只能是一個)。任何其他登錄都應映射到數據庫 (create user for login
) 以便訪問它。