サーバープリンシパルがSQL Server MS 2012の現在のセキュリティコンテキストでデータベースにアクセスできない


103

SQL Server Management Studioを介してホスティングサーバーのデータベースにアクセスしようとしていますが、ログインまでは問題ありuse myDatabaseませんが、コマンドを使用すると次のエラーが発生します。

The server principal "****" is not able to access the database "****" under the current security context.

私は検索しましたが、ホスティングサービスプロバイダーはこの問題に対するこの修正を一覧表示しています。

しかし、SQL Server Management Studio 2008が原因である可能性がありますが、SQL Server Management Studio 2012を使用しています。

これは問題になりますか?そして、もしそうなら、SSMS 2012でその代替案を誰かに教えてもらえますか?


3
「ホスティングサービスプロバイダー」?私たちは専用の話ですか、それとも共有ですか?共有ホスティングサーバーの場合は、ホスティングプロバイダーに問い合わせることを強くお勧めします。共有ホスティング環境でのSQLはバグが多く、問題が多いことで有名です。これは製品とは関係ありませんが、ホスティングプロバイダーがサーバーに適用するポリシーは異なります。すべてのホスティング会社は、SQLを活用する独自の方法を持っています。
Techie Joe 2013

回答:


80

ログインしようとしているDBにユーザーがマップされているかどうかを確認してください。


76
どうやってやるの?
Graham

3
@Graham SQL Server Management Studioを使用してユーザーを確認するか、次の回答を参照してください:stackoverflow.com/a/9356725/804773
Grambot '28 / 10/28

5
トリガーを探すことをお勧めします。それが、このメッセージを受け取った理由です。別のデータベースで、ユーザーが承認されていないトリガーを実行しました。
DanielV 2015

1
私はOPのエラーにぶつかり、この答えにたどり着きました。AzureSQL Databaseに接続する接続文字列のDatabase Nameに誤ったタイプミスがあることがわかりました。データベース名が正しい場合は、マスターにアクセスする必要はありません。それが間違っている場合、(私の場合)Entity Framework(6.1.3)は、追加情報を得るためにマスターに接続することによって、よりスマートにしようとしていると思います(ただし、EFとは無関係である可能性があります-わかりません)。しかし、私の解決策は、接続文字列が正しいことを確認することでした。不正なデータベース名の場合、非常に異なるエラーが発生すると予想していました。:-/
Jaxidian

2
@DanielVのコメントに追加するには、ストアドプロシージャをチェックして、ハードコードされたデータベース名がないか確認します。私の場合は修正しました(約20のストアドプロシージャを変更する必要がありました)。
Demonslay335 2018

26

PROD環境でSSRSにレポートをデプロイするときにも同じエラーが発生しました。問題は「use」ステートメントで再現することもできることがわかりました。解決策は、ユーザーのGUIDアカウント参照を問題のデータベースと再同期することでした(つまり、dbを復元した後のように "sp_change_users_login"を使用)。すべてのアカウントを再同期するストック(カーソル駆動)スクリプトが添付されています。

USE <your database>
GO

-------- Reset SQL user account guids ---------------------
DECLARE @UserName nvarchar(255) 
DECLARE orphanuser_cur cursor for 
      SELECT UserName = su.name 
      FROM sysusers su
      JOIN sys.server_principals sp ON sp.name = su.name
      WHERE issqluser = 1 AND
            (su.sid IS NOT NULL AND su.sid <> 0x0) AND
            suser_sname(su.sid) is null 
      ORDER BY su.name 

OPEN orphanuser_cur 
FETCH NEXT FROM orphanuser_cur INTO @UserName 

WHILE (@@fetch_status = 0)
BEGIN 
--PRINT @UserName + ' user name being resynced' 
exec sp_change_users_login 'Update_one', @UserName, @UserName 
FETCH NEXT FROM orphanuser_cur INTO @UserName 
END 

CLOSE orphanuser_cur 
DEALLOCATE orphanuser_cur

2
ありがとうございました。SQLサーバー認証を使用してデータベースをテストサーバーにコピーしましたが、アクセスできませんでした。今です
MikeH

1
ユーザーがデータベースに存在するが、ログインへのマッピングを維持できない場合は、SSMSオブジェクトエクスプローラーでそのユーザーを削除してから、ログインを再マップするとうまくいきました。そうでなければ、私は上記で提案された解決策をとる必要があると思う。
jjt

10

この問題の解決にかなりの時間を費やしましたが、接続先の特定のデータベースを忘れていたため、単純な間違いを犯していることに気付きました。資格情報を入力するために標準のSQL Server接続ウィンドウを使用していました:

SQL Server接続ウィンドウ

[ 接続プロパティ ]タブをチェックして、接続する正しいデータベースを選択していることを確認する必要がありました。[ データベースに接続 ]オプションを前のセッションからの選択に設定したままにしてしまいました。私はデータベースに接続できませんでした理由はここにあると思った私は、接続しようとしていました。

接続プロパティ

接続プロパティと他のタブを表示Options >>するには、ボタンをクリックする必要があることに注意してください。


10

これは私のために働きました:

use <Database>
EXEC  sp_change_users_login @Action='update_one', @UserNamePattern='<userLogin>',@LoginName='<userLogin>';

問題は次のように視覚化できます:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';

2
これで解決しました。よろしくお願いします!「問題を視覚化することができます」->彼らが異なるハッシュを返す場合、問題があり、上記のクエリはそれらを同期します。
2019

6

SQL ログインはサーバーレベルで定義され、特定のデータベースのユーザーにマップする必要があります。

SSMSオブジェクトエクスプローラーで、変更するサーバーの下の[ セキュリティ] > [ ログイン ]を展開し、[ログインのプロパティ]ダイアログを表示する適切なユーザーをダブルクリックします。

[ ユーザーマッピング]を選択すると、サーバー上のすべてのデータベースが表示され、既存のマッピングが選択されたデータベースが表示されます。ここから追加のデータベースを選択し(各データベースでユーザーが所属するロールを必ず選択してください)、[ OK ]をクリックしてマッピングを追加します。

ここに画像の説明を入力してください

これらのマッピングは、復元または同様の操作の後に切断される可能性があります。この場合、ユーザーはまだデータベースに存在する可能性がありますが、実際にはログインにマップされていません。その場合は、次のコマンドを実行してログインを復元できます。

USE {database};
ALTER USER {user} WITH login = {login}

DBユーザーを削除して[ログインのプロパティ]ダイアログから再作成することもできますが、ロールメンバーシップやその他の設定を再作成する必要があります。


4

私の場合、メッセージは「オブジェクト名」に誤ってデータベース名を含めた同義語が原因でした。新しい名前でデータベースを復元したとき、シノニムはまだ古いDB名を指しています。ユーザーが古いDBで権限を持っていなかったため、メッセージが表示されました。修正するために、オブジェクト名をデータベース名で修飾せずにシノニムを削除して再作成しました。

    USE [new_db]
GO

/****** Object:  Synonym [dbo].[synTable]    Script Date: 10/15/2015 9:45:01 AM ******/
DROP SYNONYM [dbo].[synTable]
GO

/****** Object:  Synonym [dbo].[synTable]    Script Date: 10/15/2015 9:45:01 AM ******/
CREATE SYNONYM [dbo].[synTable] FOR [dbo].[tTheRealTable]
GO

2

ユーザーがログインに適切にマッピングされていても、同じエラーが発生しました。

ユーザーを削除しようとした後、いくつかのSPにそのユーザーの「with execute as」が含まれていることが発見されました。

これらのSPを削除し、ユーザーを削除し、ログインにリンクされたユーザーを再作成し、SPを再作成することで、問題は解決しました。

おそらく、バックアップからの復元(関連するログインが存在しない期間中)またはスキーマの一括同期(ユーザーが存在しないかのように実行でSPを作成できる場合)から、この状態になった可能性があります。この回答に関連しています


1
SPの意味を詳しく説明できますか?
スキューバスティーブ

1
ストアドプロシージャ。SPを作成するとき(create proc xxx ...)、オプションの句「with execute as <user>」があり、現在ログインしているユーザーではなく、ユーザーがSPを実行したかのようにSPを実行することを指定します。
crokusek

1

vb.netでサーバー管理オブジェクト(SMO)を使用しているときに同じエラーが発生しました(C#でも同じです)

最初の投稿に関するTechie Joeのコメントは、共有ホスティングで多くの追加のことが行われているという有益な警告でした。少し時間がかかりましたが、以下のコードは、SQLデータベースへのアクセス方法を非常に具体的にする必要があることを示しています。「サーバープリンシパル...」エラーは、SMO呼び出しが共有ホスティング環境で正確に特定されていない場合に必ず表示されるように見えました。

このコードの最初のセクションはローカルSQL Expressサーバーに対するものであり、単純なWindows認証に依存していました。これらのサンプルで使用されているすべてのコードは、このコードプロジェクトのWebサイトの記事の Robert KanaszによるSMOチュートリアルに基づいています

  Dim conn2 = New ServerConnection()
  conn2.ServerInstance = "<local pc name>\SQLEXPRESS"
  Try
    Dim testConnection As New Server(conn2)
    Debug.WriteLine("Server: " + testConnection.Name)
    Debug.WriteLine("Edition: " + testConnection.Information.Edition)
    Debug.WriteLine(" ")

    For Each db2 As Database In testConnection.Databases
      Debug.Write(db2.Name & " - ")
      For Each fg As FileGroup In db2.FileGroups
        Debug.Write(fg.Name & " - ")
        For Each df As DataFile In fg.Files
          Debug.WriteLine(df.Name + " - " + df.FileName)
        Next
      Next
    Next
    conn2.Disconnect()

  Catch err As Exception
    Debug.WriteLine(err.Message)
  End Try

上記のコードは、ローカルのSQLEXPRESSサーバー上のすべてのデータベースの.mdfファイルを問題なく検出します。これは、認証がWindowsによって処理され、すべてのデータベースにまたがるためです。

次のコードには、.mdfファイルを反復する2つのセクションがあります。この場合、ファイルグループを探す最初の反復のみが機能し、接続は共有ホスティング環境の単一のデータベースにのみ接続されるため、単一のファイルのみが検出されます。

上記のように機能した反復のコピーである2番目の反復は、ユーザーID /パスワードが適用される共有環境ではない共有環境の最初のデータベースにアクセスしようとするため、すぐにチョークされます。 SQLサーバーは、「サーバープリンシパル...」エラーの形式で認証エラーを返します。

Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection
sqlConnection1.ConnectionString = "connection string with User ID/Password to a specific database in a shared hosting system. This string will likely also include the Data Source and Initial Catalog parameters"
Dim conn1 As New ServerConnection(sqlConnection1)
Try
  Dim testConnection As New Server(conn1)
  Debug.WriteLine("Server: " + testConnection.Name)
  Debug.WriteLine("Edition: " + testConnection.Information.Edition)
  Debug.WriteLine(" ")

  Dim db2 = testConnection.Databases("the name of the database to which the User ID/Password in the connection string applies")
  For Each fg As FileGroup In db2.FileGroups
    Debug.Write(fg.Name & " - ")
    For Each df As DataFile In fg.Files
      Debug.WriteLine(df.Name + " - " + df.FileName)
    Next
  Next

  For Each db3 As Database In testConnection.Databases
    Debug.Write(db3.Name & " - ")
    For Each fg As FileGroup In db3.FileGroups
      Debug.Write(fg.Name & " - ")
      For Each df As DataFile In fg.Files
        Debug.WriteLine(df.Name + " - " + df.FileName)
      Next
    Next
  Next

  conn1.Disconnect()

Catch err As Exception
  Debug.WriteLine(err.Message)
End Try

その2番目の反復ループではコードは正常にコンパイルされますが、SMOは正確な構文で正確なデータベースに正確にアクセスするように設定されていなかったため、失敗しました。

私はSMOを学習しているだけなので、他の初心者にもこのエラーの簡単な説明があることを知っていただければ幸いです。


0

データベースユーザーを作成したときに、「Grant Connect To」ステートメントがない可能性があります。

以下は、SQL Server DBMSに対するログインとデータベースに対するユーザーの両方を作成する必要がある完全なスニペットです

USE [master]
GO

CREATE LOGIN [SqlServerLogin] WITH PASSWORD=N'Passwordxyz', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
GO

USE [myDatabase]
GO

CREATE USER [DatabaseUser] FOR LOGIN [SqlServerLogin] WITH DEFAULT_SCHEMA=[mySchema]
GO

GRANT CONNECT TO [DatabaseUser]
GO

-- the role membership below will allow you to run a test "select" query against the tables in your database
ALTER ROLE [db_datareader] ADD MEMBER [DatabaseUser]
GO
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.