1

sp_setapproleを使用して SqlConnection にアプリケーション ロールを設定しようとすると、Windows イベント ログに次のエラーが表示されることがあります...

接続を開いたプリンシパルがその後新しいセキュリティ コンテキストを想定し、偽装されたセキュリティ コンテキストで接続をリセットしようとしたため、接続が切断されました。このシナリオはサポートされていません。Books Online の「偽装の概要」を参照してください)。

...そして、アプリケーションで一致する例外がスローされます。

これらはプールされた接続であり、接続プールがアプリの役割と互換性がない時期がありました。実際、Microsoft からの古いアドバイスは、接続プールを無効にすることでした(!!)。プールに戻す前に接続を消去します。

これらのエラーは、(理由は不明ですが) sp_unsetapprole が閉じられて接続プールに返される前に接続で実行されなかった場合に発生すると考えられます。この接続がプールから返されると、sp_approle は失敗する運命にあります。

この例外をキャッチして処理することはできますが、差し迫った障害を検出し、例外 (およびイベント ログのメッセージ) を完全に回避したいと考えています。

例外を発生させずに問題を検出することはできますか?

考えやアドバイスを歓迎します。

4

4 に答える 4

1

これは論理的に進んでおり、sp_setapprole を使用した経験はあまりありませんが、呼び出しを行う前にセキュリティ コンテキストを確認することはできませんか? または、代わりにセキュリティ許可とコンテキストを最初に確認しますか?

于 2009-02-16T13:43:42.747 に答える
1

sp_setapprole を呼び出しているが、sp_unsetapprole を呼び出しておらず、接続がプールに戻されているように見えます。

これを処理する IDisposable の実装で構造体(またはメソッド間でこれを使用する必要がある場合はクラス)を使用することをお勧めします。

public struct ConnectionManager : IDisposable
{
    // The backing for the connection.
    private SqlConnection connection;

    // The connection.
    public SqlConnection Connection { get { return connection; } }

    public void Dispose()
    {
        // If there is no connection, get out.
        if (connection == null)
        {
            // Get out.
            return;
        }

        // Make sure connection is cleaned up.
        using (SqlConnection c = connection)
        {
            // See (1).  Create the command for sp_unsetapprole
            // and then execute.
            using (SqlCommand command = ...)
            {
                // Execute the command.
                command.ExecuteNonQuery();
            }
        }
    }

    public ConnectionManager Release()
    {
        // Create a copy to return.
        ConnectionManager retVal = this;

        // Set the connection to null.
        retVal.connection = null;

        // Return the copy.
        return retVal;        
    }

    public static ConnectionManager Create()
    {
        // Create the return value, use a using statement.
        using (ConnectionManager cm = new ConnectionManager())
        {
            // Create the connection and assign here.
            // See (2).
            cm.connection = ...

            // Create the command to call sp_setapprole here.
            using (SqlCommand command = ...)
            {
                // Execute the command.
                command.ExecuteNonQuery();

                // Return the connection, but call release
                // so the connection is still live on return.
                return cm.Release();
            }
        }
    }
}
  1. sp_setapprole ストアド プロシージャの呼び出しに対応する SqlCommand を作成します。Cookie を生成して、プライベート メンバー変数に格納することもできます。
  2. ここで接続を作成します。

クライアントコードは次のようになります。

using (ConnectionManager cm = ConnectionManager.Create())
{
    // Get the SqlConnection for use.
    // No need for a using statement, when Dispose is
    // called on the connection manager, the connection will be
    // closed.
    SqlConnection connection = cm.Connection;

    // Use connection appropriately.
}
于 2009-02-17T16:00:19.147 に答える
1

いいえ、それは不可能です。

于 2009-08-25T15:47:38.927 に答える