web-dev-qa-db-ja.com

ユーザーがデータベースにアクセスできないのはなぜですか?

複数のデータベースでls_readonly権限を持っているはずのユーザーdb_datareaderを持っています。私はそれを正しく設定したと思いました:

enter image description here

しかし、ls_readonlyとしてサーバーに接続し、オブジェクトエクスプローラーでデータベースを開こうとすると、エラーが発生します。

データベースwtestにアクセスできません。 (ObjectExplorer)

masterでクエリウィンドウを開き、実行してみます。

use wtest

これは次のように応答します:

Msg 916, Level 14, State 1, Line 1
The server principal "ls_readonly" is not able to access the database "wtest" under the current security context.

何が欠けていますか?

UPDATE:ここに手がかりがあります。データベースのセキュリティコンテキストの下からユーザーとしてls_readonlyを削除すると、サーバーのセキュリティコンテキストの下のユーザーに移動し、[ユーザーマッピング]でデータベースへのアクセスを許可すると、データベースが機能し始めます。

データベースは元々、ls_readonlyユーザーがいる別のサーバーから復元された可能性があります。ユーザー識別はユーザー名に基づいていないと思いますか?

5
Shaul Behr

データベースは元々、ls_readonlyユーザーを持つ別のサーバーから復元された可能性があります。ユーザー識別はユーザー名に基づいていないと思いますか?

通常、すべてのログインは、対応するユーザーと同じsidを持っています。これがCREATE USER FROM LOGINコマンドの意味です。データベースプリンシパルは、対応するログインと同じsid(セキュリティ識別子)で作成されます。

このユーザーsidはデータベースに保存され、データベースをbackup/restoreすると、sidも保持されます。

2つのサーバーがあり、両方にls_readonlyログインしているとします。簡単にするために、最初のサーバーではls_readonlysid = 1、2番目のサーバーではsid = 2です。このログインがマップされているデータベースMyDBがあります。最初のサーバーでは、MyDBはsid = 1を格納し、2番目のサーバーではsid = 2を格納します。

最初のサーバーでMyDBデータベースをバックアップし、2番目のサーバーで復元します。これで、ログインはsid = 2になり、データベースMyDBではsid = 1になります。

ls_readonlyとしてログインし、MyDBにアクセスしようとすると、サーバーはデータベースにsid = 2があるかどうかを確認しています。存在しないため、サーバーls_readonlyはMyDBにまったくマップされていません。

これは次のようにして修正できます

alter user ls_readonly with login = ls_readonly;

このコマンドは、ls_readonlyユーザーのデータベースのsidをls_readonlyログインのsidで更新するだけです。すべての権限が保持されます。

ユーザーを削除して再作成した場合、ユーザーを削除すると、そのユーザーに付与されているすべての権限が削除されるため、それらを再度付与する必要があります。

15
sepupic

@sepupicは非常にうまく提案したすべてのものをカバーしていますが、あるSQL Serverインスタンスからバックアップされ、別のインスタンスに復元されたデータベースを復元するときに実行する次のスクリプトを共有すると思いました。復元したデータベースで実行します。基本的に、@ sepupicが話していることを自動化します。 (executeはコメント化されています)

SET NOCOUNT ON

DECLARE @cmd nVARCHAR(max) = ''

SELECT @Cmd = @cmd + 'ALTER USER ' + dp.NAME + ' WITH LOGIN = ' + dp.NAME + ';' + CHAR(10)
FROM sys.database_principals dp
LEFT JOIN master.sys.server_principals sp ON sp.NAME = dp.NAME
WHERE dp.type = 's'
    AND dp.default_schema_name <> dp.NAME
    AND sp.NAME IS NOT NULL
ORDER BY dp.NAME

PRINT @Cmd
--EXECUTE sp_executeSQL @CMD
6
Scott Hodgin

これは孤立したユーザーのように聞こえます。孤立したユーザーとは、ユーザーSIDがログインSIDと一致しない場所であり、わかりやすい名前ではありません(ログインがサーバーから削除されたか、データベースが別のサーバーから復元されたことが原因である可能性があります)。既存のすべての権限が失われるため、ユーザーを削除して再作成する必要はありません(これは単なる役割ですが、他のオブジェクトに対する個別の権限(ストアドプロシージャやテーブルなど)があると言います)。 (同じ名前であっても)ユーザーをログインに再マッピングできる機能があります。

use db1
GO
alter user [user_name] with login = [login_name]

だからそれはしたいです:

use wtest
GO
alter user [ls_readonly] with login = [ls_readonly]

MSドキュメントの詳細については こちら を参照してください

5
Simon Hellings