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, чтобы получить идентификатор вызывающего абонента, но это всегда возвращается в качестве идентификатора пула приложений для клиентов, а не для входа в систему. Потребительский пул приложений работает как сетевая служба, а сам сервер доверен для делегирования. Итак, как я могу получить зарегистрированный пользователь? Сервисный код:

    // 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;
    }

В соответствии с этим question Kerberos требуется, чтобы эта настройка работала, потому что HttpClient запускается в отдельном потоке. Однако это меня смущает, потому что я думал, что запрос отправляет заголовок авторизации, и поэтому служба должна иметь возможность использовать это и извлекать токен пользователя. Во всяком случае, я провел некоторое тестирование с Kerberos, чтобы проверить, что это правильно работает в моем домене, используя демо в "Ситуации 5" здесь, и это работает но мои два приложения по-прежнему не будут правильно передавать зарегистрированного пользователя через.

Итак, что мне нужно сделать, чтобы сделать эту работу? Требуется ли Kerberos или мне нужно что-то сделать в моей службе, чтобы распаковать заголовок авторизации и создать основной объект из токена? Все советы были оценены.

Ответы

Ответ 1

Ключ должен позволить вашему приложению (потребителю) MVC олицетворять вызывающего пользователя и затем синхронно выдавать HTTP-запросы (т.е. не порождать новый поток). Вам не нужно беспокоиться о деталях реализации на низком уровне, таких как NTLM и Kerberos.

Потребитель

Настройте приложение MVC следующим образом:

  • Запустить диспетчер IIS
  • Выберите веб-приложение MVC
  • Дважды нажмите "Аутентификация"
  • Включить "олицетворение ASP.NET"
  • Включить "Аутентификация Windows
  • Отключить другие формы аутентификации (если, возможно, не дайджест, если вам это нужно)
  • Откройте файл Web.config в корневом каталоге вашего приложения 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);

Сервис

Настройте службу веб-API так:

  • Запустить диспетчер IIS
  • Выберите службу веб-API
  • Дважды нажмите "Аутентификация"
  • Отключить "олицетворение ASP.NET".
  • Включить "Аутентификация Windows
  • Если только подмножество методов веб-API требует аутентификации пользователей, оставьте "Анонимная аутентификация" включенной.
  • Откройте файл Web.config в корневой папке службы веб-API и убедитесь, что <authentication mode="Windows" />

Я вижу, что вы уже украсили свой метод с атрибутом [Authorize], который должен инициировать вызов проверки подлинности (HTTP 401) при обращении к этому методу. Теперь вы сможете получить доступ к идентификатору вашего конечного пользователя с помощью свойства User.Identity вашего класса ApiController.

Ответ 2

Ключевой проблемой с двойным переходом является делегирование учетных данных пользователя во второй вызов. Я хочу немного рассказать об этом. C1 = клиентский браузер, S1 = Первый сервер, S2 = Второй сервер.

Предположим, что наша полная проверка подлинности окна поддержки системы. Когда пользователь получает доступ к S1 из браузера, его учетные данные окна по умолчанию передаются на сервер S1, но когда S1 выполняет вызов S2, по умолчанию он не передает учетные данные для S2.

Разрешение:

  • Мы должны включить проверку подлинности/олицетворение окна на обеих машинах.
  • Нам нужно включить делегирование между сервером, чтобы 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/

Ответ 3

Если вы пытаетесь получить доступ к сервису, который размещен на проверке подлинности Windows, выполните следующие действия.

var request = new RestRequest(Method.POST);

Если вы хотите использовать учетные данные по умолчанию для приложений, которые должны иметь доступ к серверу размещенных сервисов

request.UseDefaultCredentials = true;

или пользователя ниже, чтобы передать учетные данные вручную

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