web-dev-qa-db-ja.com

HttpClient&Windows Auth:ログインしたコンシューマーのユーザーをサービスに渡す

ユーザーがコンシューマーにログインしたときにサービスが実行されるサービスとコンシューマーを理解して設定するのに苦労しています。

私の消費者は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は必要ですか、それともサービスで承認ヘッダーを解凍してトークンからプリンシパルオブジェクトを作成するために何かする必要がありますか?すべてのアドバイスに感謝します。

17
James

重要なのは、MVCアプリケーション(コンシューマー)が呼び出し元のユーザーになりすまして、HTTPリクエストを同期的に(つまり、新しいスレッドを生成せずに)発行することです。 NTLMとKerberosのような低レベルの実装の詳細を気にする必要はありません。

消費者

MVCアプリケーションを次のように構成します。

  1. 開始IISマネージャ
  2. MVC Webアプリケーションを選択します
  3. 「認証」をダブルクリックします
  4. Enable 'ASP.NET偽装'
  5. Enable 'Windows認証'
  6. Disable他の認証形式(必要な場合はおそらくダイジェストを除く)
  7. MVCアプリケーションのルートにあるWeb.configファイルを開き、<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サービスを構成します。

  1. 開始IISマネージャ
  2. Web APIサービスを選択します
  3. 「認証」をダブルクリックします
  4. Disable 'ASP.NET Impersonation'。
  5. Enable 'Windows認証'
  6. Web APIメソッドのサブセットのみでユーザーの認証が必要な場合は、「匿名認証」を有効のままにしておきます。
  7. Web APIサービスのルートにあるWeb.configファイルを開き、<authentication mode="Windows" />

メソッドにアクセスしたときに認証チャレンジ(HTTP 401)をトリガーする[Authorize]属性でメソッドをすでに装飾していることがわかります。これで、ApiControllerクラスのUser.Identityプロパティを介してエンドユーザーのIDにアクセスできるようになります。

ダブルホップの主な問題は、ユーザー資格情報の2番目の呼び出しへの委任です。それについて少し詳しく説明したいと思います。 C1 =クライアントブラウザ、S1 =最初のサーバー、S2 = 2番目のサーバー。

完全なシステムサポートウィンドウ認証を想定します。ユーザーがブラウザからS1にアクセスすると、そのデフォルトのウィンドウ認証情報がサーバーS1に渡されますが、S1がS2を呼び出すとき、デフォルトでは認証情報はS2に渡されません。

解決 :

  1. 両方のマシンでウィンドウ認証/偽装を有効にする必要があります。
  2. 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/

0
Rahul Garg

Windows認証でホストされているサービスにアクセスしようとしている場合は、次の手順に従ってください。

var request = new RestRequest(Method.POST);

ホストされたサービスサーバーにアクセスする必要があるアプリケーションのデフォルト認証情報を使用する場合

request.UseDefaultCredentials = true;

or資格情報を手動で渡すための以下のユーザー

request.Credentials = new NetworkCredential("Username", "Password", "Domain");
0