ビジネスレイヤーサーバーにWebフロントエンドがあります。
Web アプリケーションの特定のページは、非常に長時間実行されるタスクをインスタンス化します (最大で 10 分以上かかる場合があります)。これらのリクエストは次のように処理されます: -
(HTTP 要求スレッドで)
- ビジネスサーバーに接続します。
- 接続オブジェクトを渡す長時間の呼び出しを行う新しいスレッドを作成します。
- 次に、HTTP 要求が完了し、ハンドルがブラウザに返されます。
- ブラウザーは Web サーバーを定期的にポーリングして、実行時間の長いタスクの進行状況に関する最新情報を取得します。
ビジネス サーバーへのすべての要求は認証されます。接続のユーザー プリンシパル ページには、ビジネス サーバー上のメソッドを呼び出す権限が必要です。
このメカニズムは、Web アプリケーションがクラシック モードで実行されている限り正常に機能します。パイプライン モードで実行すると、ブラウザーのポーリング時に ObjectDisposedExceptions が発生します。
System.ObjectDisposedException: Safe handle has been closed
at System.StubHelpers.StubHelpers.SafeHandleC2NHelper(Object pThis, IntPtr CleanupWorkList)
at Microsoft.Win32.Win32Native.GetTokenInformation(SafeTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, ref UInt32 ReturnLength)
at System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeTokenHandle tokenHandle, TokenInformationClass tokenInformationClass, ref UInt32 dwLength)
at System.Security.Principal.WindowsIdentity.get_User()
at System.Security.Principal.WindowsIdentity.GetName()
at System.Security.Principal.WindowsIdentity.get_Name()
問題は、接続を確立するために使用された Windows プリンシパルが、元の要求が終了したときに破棄されることです (これは理解できます - 実際、コードがまったく機能したことに驚いています!)。
この問題を回避する方法として、HTTP リクエスト プリンシパルの複製を作成し、それを使用して接続を作成する (そして、長時間実行されるタスクが完了したら破棄する) ことが可能か、または、プリンシパルが破棄された後でも、ワーカー スレッドの HTTP 要求の原則は?
アップデート
(Aliostad の質問に対する私のコメントは間違っていました。テスト ページは失敗しました。実際の (障害のある) コードと同じコード パスを実行しないように、テスト ページを作成するのに十分な混乱をきたしました。気にしないでください!)
この問題の「回避策」を書きました: - ビジネス サーバーへの呼び出しが行われる前に、ビジネス サーバー ロジックがどのロール/グループを照会するかを知っている幸運な立場にあります。したがって、私の回避策は、これらのロールのリクエストのプリンシパルのメンバーシップに基づいて、新しい汎用プリンシパルを作成することです。長時間実行タスクは、汎用プリンシパルを使用して実行されます。
私はこの回避策に 100% 満足しているわけではありません。なぜなら、これは非常に「ハック」だからです。つまり、プリンシパルの ID が認証されていることを検証する (非常に賢明な) チェックを何らかのロジックで行うと、簡単に失敗することがわかります。
ですから、この問題についての助けや洞察をいただければ幸いです。
ありがとう