SharePoint 2010 のカスタム クレーム プロバイダーで Secure Store Service を使用する
先日、カスタム クレーム プロバイダーで Secure Store Service (SSS) を使用して作業していたとき、私は珍しい問題点に気付きました。これは実際に興味深いシナリオです。というのも、多くの人々が実行したいと思うカスタム クレーム拡張を行っていたからです。私は、各ユーザーに関する追加情報をクエリし、その情報を使用して拡張すべきクレームを判断するため、リモート データ ソースに接続する必要がありました。
カスタム クレーム プロバイダーでのデータ ソースの使用に関する一般的なガイドラインとして重要なことは、カスタム クレーム プロバイダー アセンブリが SharePoint STS プロセスによってメモリに保持されるということです。このため、「情報 (データセットや資格情報のセットなど)」は、クラス レベル変数に格納することで非常に簡単に取得できるようになり、次の IISRESET まで利用できるようになります。ここで大きな制約となるのは、カスタム クレーム プロバイダー クラスがインスタンス化されたときに、必ずしもすべての SharePoint ファーム リソースが使用できるわけではないということです。これが今回の話の教訓です。
今回の特殊事例では、私はカスタム クレーム プロバイダーのコンストラクター内で SSS からデータを取得し、そのデータを使用して「他の作業」を行おうとしていました。一方向の信頼を横断するドメインから WindowsIdentity を作成し、それを使用して、リモート Active Directory をクエリする権限を持つ権限借用コンテキストを作成しようとしていたのです。問題が発生したのはコンストラクター内で SSS への参照を使用して何かをしようとしたときで、必ずタイムアウトになりました。SSS 上でどのメソッドを呼び出しても、60 秒後には必ずタイムアウト エラーで失敗しました。
修正策は、そのコードをコンストラクターの外部に移すだけでした。自分でオーバーライドした FillClaimsForEntity メソッドからまったく同じコードを呼び出すと、正しく動作しました。私がこの方法を見つけ出したのはまさに幸運と試行錯誤によるものであり、共有すべきヒントのように思われました。
この特殊な問題 (リモート ドメインにログインしての権限借用) の原因を解明するにあたり、この状況を回避する別のパターンや、別の問題点を提示することには意味があるでしょう。
前述のように、アセンブリは STS プロセスにロードされたままなので、クラス レベル変数を「保持」できます。リモート ドメインをクエリする必要があるときに、当然、そのドメインに何度もログインしたくはないので、自分の WindowsIdentity 用のクラス レベル変数を作成しました。パターンは次のようになります。
- SSS の資格証明を取得済みかどうか確認する
- 取得していない場合は、次のコードを実行する
- SSS から資格証明を取得する
- LogonUser API を使用して、SSS から取得した資格証明でリモート ドメインにログオンする
- 自分の WindowsIdentity 変数をインスタンス化し、リモート ユーザーの資格証明を保持する
- 取得していない場合は、次のコードを実行する
- 自分の WindowsIdentity 変数が null かどうかチェックする
- null でない場合は、次のコードを実行する
- WindowsIdentity.Impersonate() で WindowsImpersonationContext の新しいインスタンスを作成する
- リモート ドメインをクエリする
- 作成した WindowsImpersonationContext に対して Undo を呼び出す
- null でない場合は、次のコードを実行する
このパターンは正しく機能するように思われますし、ほぼ最大のパフォーマンスを引き出せます。ここで問題となるのは、WindowsIdentity インスタンスに対して Impersonate() を呼び出さず、作成される WindowsImpersonationContext に対して後で Undo を呼び出さない場合です。権限借用を元に戻さないと、私の経験では、サイトが表示されなくなります。Undo 呼び出しを元どおりに追加すれば、またすべてが正しく動作し始めます。
これはローカライズされたブログ投稿です。原文の記事は、「Using Secure Store Service in a Custom Claims Provider with SharePoint 2010」をご覧ください。