С помощью HttpClient и Windows авторизации: пароль пользователя, вошедшего в систему бытового обслуживания
Я изо всех сил пытаюсь понять и настроить службу и потребителя, где служба будет работать как пользователь, вошедший в систему потребителя.
Мой потребитель-это приложение 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;
}
Согласно этому вопросу, Kerberos требуется, чтобы эта настройка работала, потому что HttpClient выполняется в отдельном потоке. Однако это сбивает меня с толку, потому что я думал, что запрос отправляет заголовок авторизации, и поэтому служба должна иметь возможность использовать это и получить маркер пользователя. В любом случае, я провел некоторые тесты с Kerberos чтобы проверить, что это правильно работает на моем домене, используя демонстрацию в "ситуации 5" здесь , и это работает, но мои два приложения все еще не могут правильно передать зарегистрированного пользователя.
Итак, что мне нужно сделать, чтобы это сработало? Нужен ли Kerberos или мне нужно что-то сделать в моей службе, чтобы распаковать заголовок авторизации и создать основной объект из маркера? Все советы ценил.
3 ответов:
Ключ состоит в том, чтобы позволить вашему приложению MVC (потребителю) олицетворять вызывающего пользователя, а затем выдавать запросы HTTP синхронно (т. е. без порождения нового потока). Вам не нужно беспокоиться о деталях реализации низкого уровня, таких как NTLM vs Kerberos.
Потребитель
Настройте приложение MVC следующим образом:
- запустите диспетчер IIS
- выберите веб-приложение MVC
- двойной щелчок по кнопке "Аутентификация"
- включить 'ASP.NET олицетворение'
- Включить 'Аутентификацию Windows'
- отключить другие формы аутентификации (если, возможно, не дайджест, если вам это нужно)
- откройте веб.конфигурационный файл в корне вашего приложения 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 сервис Вот так:
- запустите диспетчер IIS
- выберите свой веб-API сервис
- дважды щелкните на "аутентификация"
- отключить 'ASP.NET олицетворение".
- Включить 'Аутентификацию Windows'
- Если аутентификация пользователей требуется только для подмножества методов веб-API, оставьте "анонимную аутентификацию" включенной.
- откройте веб.конфигурационный файл в корне службы Web API и убедитесь, что
<authentication mode="Windows" />Я вижу, что вы уже украсили свой метод атрибутом
[Authorize], который должен вызвать вызов аутентификации (HTTP 401) при обращении к методу. Теперь вы должны иметь возможность получить доступ к идентификатору вашего конечного пользователя через свойствоUser.Identityвашего класса ApiController.
Ключевой проблемой двойного прыжка является делегирование учетных данных пользователя второму вызову. Я хочу немного подробнее рассказать об этом. 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/
Если вы пытаетесь получить доступ к службе, которая размещена на аутентификации windows, то выполните следующие действия.
var request = new RestRequest(Method.POST);Если вы хотите использовать учетные данные приложений по умолчанию, которые должны иметь доступ на сервере размещенной службы
request.UseDefaultCredentials = true;или пользователь ниже, чтобы передать учетные данные вручную
request.Credentials = new NetworkCredential("Username", "Password", "Domain");
Comments