3 に答える
新しいスレッドでプリンシパルを失う問題については、ここで言及されています。
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 コンストラクトであり、自己ホスト時には存在しないため不可能です)。
カスタムMessageHandlerを使用して、次のように定義されMS_UserPrincipal
た拡張メソッドを呼び出すことにより、プロパティを追加できます。HttpRequestMessageExtensionMethods.SetUserPrincipal
System.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に接続されているユーザーを変更しないことに注意してください。
コンテキストの切り替えを回避する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;
}