ユーザーがコンシューマーにログインしたときにサービスが実行されるサービスとコンシューマーを理解して設定するのに苦労しています。
私の消費者はMVCアプリケーションです。私のサービスはWeb APIアプリケーションです。どちらも同じドメイン内の別々のサーバーで実行されます。どちらもWindows Authを使用するように設定されています。
私の消費者コードは:
private T GenericGet<T>(string p)
{
T result = default(T);
HttpClientHandler handler = new HttpClientHandler() { PreAuthenticate = true, UseDefaultCredentials = true };
using (HttpClient client = new HttpClient(handler))
{
client.BaseAddress = new Uri(serviceEndPoint);
HttpResponseMessage response = client.GetAsync(p).Result;
if (response.IsSuccessStatusCode)
result = response.Content.ReadAsAsync<T>().Result;
}
return result;
}
私のサービスではUser.Identity.Name
を呼び出して発信者IDを取得していますが、これは常に、ログインしたユーザーではなく、コンシューマーアプリプールIDとして返されます。コンシューマーアプリプールはネットワークサービスとして実行されており、サーバー自体は委任に対して信頼されています。ログインしたユーザーを取得するにはどうすればよいですか?サービスコード:
// GET: /Modules/5/Permissions/
[Authorize]
public ModulePermissionsDTO Get(int ModuleID)
{
Module module= moduleRepository.Find(ModuleID);
if (module== null)
throw new HttpResponseException(HttpStatusCode.NotFound);
// This just shows as the App Pool the MVC consumer is running as (Network Service).
IPrincipal loggedInUser = User;
// Do I need to do something with this instead?
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
ModulePermissionsDTO dto = new ModulePermissionsDTO();
// Construct object here based on User...
return dto;
}
この 質問 によると、HttpClientは別のスレッドで実行されるため、この設定を機能させるにはKerberosが必要です。しかし、リクエストがAuthorizationヘッダーを送信すると思ったので、サービスがこれを使用してユーザートークンを取得できるはずなので、これは私を混乱させます。とにかく、私はKerberosでいくつかのテストを行って、これが「状況5」のデモを使用して私のドメインで正しく機能することを確認しました ここ これは機能しますが、 2つのアプリケーションは、まだログインしているユーザーを正しく渡しません。
それで、これを機能させるために何をする必要がありますか? Kerberosは必要ですか、それともサービスで承認ヘッダーを解凍してトークンからプリンシパルオブジェクトを作成するために何かする必要がありますか?すべてのアドバイスに感謝します。
重要なのは、MVCアプリケーション(コンシューマー)が呼び出し元のユーザーになりすまして、HTTPリクエストを同期的に(つまり、新しいスレッドを生成せずに)発行することです。 NTLMとKerberosのような低レベルの実装の詳細を気にする必要はありません。
MVCアプリケーションを次のように構成します。
<authentication mode="Windows" />
HTTPリクエストを発行するには、優れた RestSharp ライブラリを使用することをお勧めします。例:
var client = new RestClient("<your base url here>");
client.Authenticator = new NtlmAuthenticator();
var request = new RestRequest("Modules/5/Permissions", Method.GET);
var response = client.Execute<ModulePermissionsDTO>(request);
次のようにWeb APIサービスを構成します。
<authentication mode="Windows" />
メソッドにアクセスしたときに認証チャレンジ(HTTP 401)をトリガーする[Authorize]
属性でメソッドをすでに装飾していることがわかります。これで、ApiControllerクラスのUser.Identity
プロパティを介してエンドユーザーのIDにアクセスできるようになります。
ダブルホップの主な問題は、ユーザー資格情報の2番目の呼び出しへの委任です。それについて少し詳しく説明したいと思います。 C1 =クライアントブラウザ、S1 =最初のサーバー、S2 = 2番目のサーバー。
完全なシステムサポートウィンドウ認証を想定します。ユーザーがブラウザからS1にアクセスすると、そのデフォルトのウィンドウ認証情報がサーバーS1に渡されますが、S1がS2を呼び出すとき、デフォルトでは認証情報はS2に渡されません。
解決 :
以下のリンクでいくつかの便利な詳細を見つけることができます:http://blogs.msdn.com/b/farukcelik/archive/2008/01/02/how-to-set-up-a-kerberos-authentication-scenario-with- sql-server-linked-servers.aspx
https://sqlbadboy.wordpress.com/2013/10/11/the-kerberos-double-hop-problem/
Windows認証でホストされているサービスにアクセスしようとしている場合は、次の手順に従ってください。
var request = new RestRequest(Method.POST);
ホストされたサービスサーバーにアクセスする必要があるアプリケーションのデフォルト認証情報を使用する場合
request.UseDefaultCredentials = true;
or資格情報を手動で渡すための以下のユーザー
request.Credentials = new NetworkCredential("Username", "Password", "Domain");