Как написать код, который вызывает службу WCF и откатывается от Kerberos к NTLM, если это необходимо? - PullRequest
8 голосов
/ 09 сентября 2010

Мне нужно вызвать службу WCF программно. Служба может быть размещена с аутентификацией NTLM или Kerberos и должна работать в любом из них. То есть, если подключение к сервису через Kerberos не удается, тогда оно должно вернуться к NTLM.

Вот код, который я использую для аутентификации Kerberos (при необходимости служба размещается в SharePoint 2010 и вызывается из веб-части):

public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
    var binding = new BasicHttpBinding();
    binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
    url = url.EndsWith("/") ? url + SiteMembershipAddress : url + "/" + SiteMembershipAddress;
    var endpoint = new EndpointAddress(url);
    var proxy = new SiteMembershipSvc.SiteMembershipServiceClient(binding, endpoint);
    proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    return proxy;
}

Вызов метода на прокси при запуске в среде NTLM выдает ошибку:

HTTP-запрос не авторизован с схема аутентификации клиента «Переговоры». Заголовок аутентификации получен от сервера 'NTLM'.

Примечание. URL-адрес может находиться в другом веб-приложении на другом сервере. Я не могу проверить, под какой аутентификацией работает веб-приложение веб-части, и предположить, что оно совпадает с местом размещения службы WCF.

Как я могу (автоматически или вручную) обеспечить, чтобы при сбое аутентификация возвращалась из Kerberos обратно в NTLM? Обновление:

Как уже упоминалось, ошибка аутентификации возникает при вызове веб-метода. Однако я не хочу ждать так долго, поскольку в службе есть несколько веб-методов, вызываемых из нескольких мест. Я хотел бы проверить аутентификацию в точке, где настроен прокси (во фрагменте кода выше).

Я пытался использовать proxy.Open(), но это не похоже на сбой.

Ответы [ 7 ]

1 голос
/ 09 сентября 2010

Это немного не так, но почему он возвращается к NTLM.У меня были значительные трудности с безопасностью в активном каталоге и WCF, связанных с именами участников службы (SPN).

Kerberos не будет работать, если вы запускаете службу как что-то отличное от сетевой службы, если у вас нет SPN, объявленного в домене для вашей службы.Чтобы установить имя участника-службы, вам необходим административный комплект Windows-сервера, в котором есть команда setspn.

setspn -A HTTP\machinename domain\service_account

Это позволит Kerberos предоставлять учетные данные клиента вашей службе в домене.

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

1 голос
/ 15 октября 2015

(я узнаю, что оригинальная запись очень старая.)

Можете ли вы использовать что-то кроме BasicHttpBinding (например, WsHttpBinding)?Согласно этой статье, BasicHttpBinding является единственным исключением для объектов привязки, поскольку он не выполняет автоматическое согласование.Вот почему allowNTLM не имеет никакого эффекта.

0 голосов
/ 10 мая 2011

Мне не удалось найти способ сделать это автоматически. Вместо этого я добавил пользовательский интерфейс в приложение, где должен быть выбран тип аутентификации.

0 голосов
/ 26 сентября 2010

Если ваш Kerberos выходит из строя, он автоматически по умолчанию будет NTLM, вам не нужно делать ничего особенного.

http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part1.html

http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part2.html

http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part3.html

0 голосов
/ 22 сентября 2010

Я полагаю, вы используете полное DNS-имя сервера в качестве адреса службы. Попробуйте использовать имя NETBIOS или IP-адрес. Это должно заставить его использовать NTLM.

Если вы знаете, какой протокол использует сервер, вы можете настроить приложение на использование либо полного имени, либо ip.

Надеюсь, что это работает для вас.

0 голосов
/ 10 сентября 2010

Попробуйте установить:

proxy.ClientCredentials.Windows.AllowNTLM = true;

Согласно этому , AllowNTLM теперь устарел - я не уверен, какова правильная альтернатива.

0 голосов
/ 09 сентября 2010

У меня была такая же ошибка, которую я выложил около здесь и решил ее, создав динамическую конечную точку следующим образом:

public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
    //create endpoint
    EndpointAddress ep = new EndpointAddress(new Uri(string), EndpointIdentity.CreateUpnIdentity("MyDomain\WCFRunAsUser"));
    //create proxy with new endpoint
    SiteMembershipSvc.SiteMembershipServiceClient service = new SiteMembershipSvc.SiteMembershipServiceClient("wsHttp", ep);
    //allow client to impersonate user
    service.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    //return our shiny new service
    return service;
}

Я запускал службу WCF как отдельный пользователь Active Directory, а не как NETWORK_SERVICE по умолчанию.

...