53
4

3 に答える 3

78

新しいスレッドでプリンシパルを失う問題については、ここで言及されています。

http://leastprivilege.com/2012/06/25/important-setting-the-client-principal-in-asp-net-web-api/

重要: ASP.NET Web API でのクライアント プリンシパルの設定

ASP.NET の奥深くに埋もれているいくつかの不幸なメカニズムのため、Web API Web ホスティングで Thread.CurrentPrincipal を設定するだけでは十分ではありません。

ASP.NET でホストしている場合、新しいスレッドの作成時に Thread.CurrentPrincipal が HttpContext.Current.User でオーバーライドされることがあります。つまり、スレッドと HTTP コンテキストの両方でプリンシパルを設定する必要があります。

そしてここ: http://aspnetwebstack.codeplex.com/workitem/264

現在、Web ホスト シナリオでカスタム メッセージ ハンドラーを使用して認証を実行する場合は、ユーザー プリンシパルに次の両方を設定する必要があります。

IPrincipal principal = new GenericPrincipal(
    new GenericIdentity("myuser"), new string[] { "myrole" });
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;

最後の行HttpContext.Current.User = principal(needs using System.Web;) をメッセージ ハンドラーに追加しました。MediaTypeFormatter のタスクによってスレッドが変更された場合でも、Userプロパティは常に正しいプリンシパルを持ちます。ApiController

編集

HttpContext強調しておくと、WebApi が ASP.NET/IIS でホストされている場合にのみ、現在のユーザーのプリンシパルを設定する必要があります。自己ホストの場合は必要ありません (またHttpContext、ASP.NET コンストラクトであり、自己ホスト時には存在しないため不可能です)。

于 2012-08-19T23:25:55.100 に答える
5

カスタムMessageHandlerを使用して、次のように定義されMS_UserPrincipalた拡張メソッドを呼び出すことにより、プロパティを追加できます。HttpRequestMessageExtensionMethods.SetUserPrincipalSystem.ServiceModel.Channels

protected override Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
{
    var user = new GenericPrincipal(new GenericIdentity("UserID"), null);
    request.SetUserPrincipal(user);
    return base.SendAsync(request, cancellationToken);
}

これは、このプロパティをリクエストのプロパティコレクションに追加するだけであり、ApiControllerに接続されているユーザーを変更しないことに注意してください。

于 2012-09-14T14:51:42.123 に答える
5

コンテキストの切り替えを回避するTaskCompletionSource<object>には、カスタムで別のタスクを手動で開始する代わりに、を使用してみてMediaTypeFormatterください。

public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
    var tcs = new TaskCompletionSource<object>();

    // some formatting happens and finally a TestModel is returned,
    // simulated here by just an empty model
    var testModel = new TestModel();

    tcs.SetResult(testModel);
    return tcs.Task;
}
于 2012-08-19T20:22:15.940 に答える