2013-05-14 1 views
6

ASP.NET WebAPIを使用して、認証中にコントローラが後でApiController.Userプロパティを使用できるようにThread.CurrentPrincipalが設定されています。Thread.CurrentPrincipalを非同期に設定しますか?

認証ステップが非同期(別のシステムを参照)になると、CurrentPrincipalの突然変異が失われます(呼び出し元のawaitが同期コンテキストを復元するとき)。

はここでは非常に単純化した例を示します(実際のコードでは、認証は、アクションフィルタで起こる):

using System.Diagnostics; 
using System.Security.Principal; 
using System.Threading; 
using System.Threading.Tasks; 

public class ExampleAsyncController : System.Web.Http.ApiController 
{ 
    public async Task GetAsync() 
    { 
     await AuthenticateAsync(); 

     // The await above saved/restored the current synchronization 
     // context, thus undoing the assignment in AuthenticateAsync(). 
     Debug.Assert(User is GenericPrincipal); 
    } 

    private static async Task AuthenticateAsync() 
    { 
     // Save the current HttpContext because it's null after await. 
     var currentHttpContext = System.Web.HttpContext.Current; 

     // Asynchronously determine identity. 
     await Task.Delay(1000); 
     var identity = new GenericIdentity("<name>"); 

     var roles = new string[] { }; 
     Thread.CurrentPrincipal = new GenericPrincipal(identity, roles); 
     currentHttpContext.User = Thread.CurrentPrincipal; 
    } 
} 

はどのようにして、発信者のawaitは、その変異を破棄しないように、非同期機能でThread.CurrentPrincipalを設定してください同期コンテキストを復元するとき

+1

私はあなたの問題についてはわかりませんが、理想的には、コントローラが呼び出される前に認証することをお勧めします。私のWebAPIプロジェクトでは、コントローラに到達する前に認証を行う 'DelegatingHandler'をセットアップするのが好きです。 – Matthew

+0

@Matthew、私は同意し、実際のコードがどのように動作するのか、コントローラーメソッドが呼び出される前にアクションフィルターが認証を処理します。私は私の例を単純化するためにアクションフィルタを除外しましたが、どちらの状況でも問題は同じです。 –

+0

CurrentPrincipalを設定すると、このスタックオーバーフローの応答が表示されます。これは、呼び出しスレッドに持続します:http://stackoverflow.com/a/12460170/507793それ以外の場合は、問題を解決する方法がわかりません。 – Matthew

答えて

7

HttpContext.Current.Userも設定する必要があります。詳細は、this answerおよびthis blog postを参照してください。

更新:また、あなたは.NET 4.5上で実行されていることを確認してtrueUserTaskFriendlySynchronizationContextセットを持っています。

+0

スティーブンのお手伝いをありがとう。 'HttpContext.Current.User'の設定を追加しました(私の質問でコードを更新しました)が、それは役に立ちません。問題は変わりません。 –

+0

それは間違いなく私のために働いています。私は、上記のコードでValuesControllerの新しいWebAPIプロジェクトを作成します。うまく動作します。フォローアップの質問:.NET 4.5で動作していて、 'UseTaskFriendlySynchronizationContext'がtrueに設定されていますか? –

+0

'UseTaskFriendlySynchronizationContext'をtrueに設定して問題を解決しました!調査に時間を割いていただきありがとうございます! –

関連する問題