17

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

私のコンシューマは MVC アプリケーションです。My Service は Web API アプリケーションです。どちらも同じドメイン内の別のサーバーで実行されます。どちらも Windows 認証を使用するように設定されています。

私の消費者コードは次のとおりです。

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 ヘッダーを送信すると考えたため、サービスはこれを使用してユーザートークンを取得できるはずなので、これは私を混乱させます。とにかく、ここで「状況 5」のデモを使用して、これが私のドメインで正しく機能することを確認するために Kerberos でいくつかのテストを行いました。

では、これを機能させるにはどうすればよいでしょうか。Kerberos は必要ですか、それともサービスで Authorization ヘッダーをアンパックしてトークンからプリンシパル オブジェクトを作成する必要がありますか? すべてのアドバイスに感謝します。

4

3 に答える 3

16

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

消費者

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

  1. IIS マネージャーを起動する
  2. MVC Web アプリケーションを選択します
  3. 「認証」をダブルクリック
  4. 「ASP.NET 偽装」を有効にする
  5. 「Windows 認証」を有効にする
  6. 他の形式の認証を無効にします (必要に応じておそらく Digest を除く)
  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. 「ASP.NET 偽装」を無効にします。
  5. 「Windows 認証」を有効にする
  6. Web API メソッドのサブセットのみでユーザーの認証が必要な場合は、[匿名認証] を有効のままにします。
  7. Web API サービスのルートにある Web.config ファイルを開き、次のことを確認します。<authentication mode="Windows" />

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

于 2013-10-14T11:36:40.810 に答える
0

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

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

解像度 :

  1. 両方のマシンでウィンドウ認証/偽装を有効にする必要があります。
  2. S1 が S2 を信頼し、資格情報を S2 に渡すことができるように、サーバー間の委任を有効にする必要があります。

以下のリンクで役立つ詳細を見つけることができます。 sql-server-linked-servers.aspx

https://sqlbadboy.wordpress.com/2013/10/11/the-kerberos-double-hop-problem/

于 2015-07-14T10:41:48.247 に答える