У меня есть клиент, который отправляет простой веб-запрос в службу SOAP. Это простая C# программа, использующая файл WSDL службы для создания клиента. Служба размещена на IIS 8.5 и Windows Server 2012. Она отлично работает при использовании анонимной аутентификации, но не работает с Windows аутентификацией. И клиент, и служба находятся в одном домене, с правами пользователя тоже все в порядке.
Я настроил IIS так, чтобы он отключал все формы проверки подлинности, кроме Windows (Negotiate, NTLM). Клиент настроен так, что он использует Windows в качестве типа учетных данных клиента.
Когда я отправляю запрос, я получаю следующую ошибку: "HTTP-запрос не авторизован с помощью схемы проверки подлинности клиента« Согласование » Заголовок аутентификации, полученный от сервера, был 'Negotiate, NTLM' "
. Затем я попробовал инструмент, найденный на github, под названием " WebServiceStudio ". С помощью этого инструмента я установил WSDL, выбрал метод запроса, и он работал, даже с аутентификацией Windows.
Я просмотрел обе попытки с помощью Wireshark и заметил, что запрос WebServiceStudio немедленно отправляет токен Negotiate с первым запрос, в то время как мой собственный клиент отправляет токен во втором запросе, который, насколько я понимаю, обычно работает Windows аутентификация.
Я пробовал на стороне IIS, но пока ничего не получалось:
- Изменен порядок проверки подлинности (согласование, NTLM и NTLM, согласование)
- Изменена проверка подлинности только на согласование
- Изменена расширенная защита в расширенных настройках (ни один из вариантов не имел значения )
- Проверено, что оба модуля WindowsAuthentication и WindowsAuthenticationModule были установлены
Моя цель заключается в том, чтобы мой собственный клиент C# мог успешно пройти аутентификацию с Windows аутентификацией.
Вот конфигурация C# клиента:
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.serviceModel>
<client>
<endpoint address="server address" binding="basicHttpBinding"
bindingConfiguration="MyContractSoap" contract="MyContract.MyContractSoap" />
</client>
<bindings>
<basicHttpBinding>
<binding name="MyContractSoap">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
А вот данные wireshark по запросу моего клиента:
POST /ABC/ShipmentDocuments.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "ABC/DocumentShipped"
Host: sdespte3
Content-Length: 333
Expect: 100-continue
Accept-Encoding: gzip, deflate
<!-- Server rejects request and states authentication method -->
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Tue, 18 Feb 2020 10:20:01 GMT
Content-Length: 1344
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>401 - Nicht autorisiert: Zugriff aufgrund ung.ltiger Anmeldeinformationen verweigert.</title>
</head>
<body>
<div id="header"><h1>Serverfehler</h1></div>
<div id="content">
<div class="content-container"><fieldset>
<h2>401 - Nicht autorisiert: Zugriff aufgrund ung.ltiger Anmeldeinformationen verweigert.</h2>
<h3>Die angegebenen Anmeldeinformationen berechtigen Sie nicht, dieses Verzeichnis oder diese Seite anzuzeigen.</h3>
</fieldset></div>
</div>
</body>
</html>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>Request data here</s:Body></s:Envelope>
<!-- We send the negotiate token -->
POST /ABC/ShipmentDocuments.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "ABC/DocumentShipped"
Accept-Encoding: gzip, deflate
Authorization: Negotiate YIIHog...Token here
Host: abc
Content-Length: 333
Expect: 100-continue
<!-- Rejected again, unsure why -->
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Tue, 18 Feb 2020 10:20:01 GMT
Content-Length: 1344
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>401 - Nicht autorisiert: Zugriff aufgrund ung.ltiger Anmeldeinformationen verweigert.</title>
<style type="text/css">
И, наконец, данные wireshark другого работающего инструмента:
POST /ABC/ShipmentDocuments.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "ABC/DocumentShipped"
Authorization: Negotiate YIILV...Token here
Host: sdespiis1
Content-Length: 415
Expect: 100-continue
HTTP/1.1 100 Continue
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body>Request body here</soap:Body></soap:Envelope>
<!-- Accepted -->
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: false
X-Powered-By: ASP.NET
WWW-Authenticate: Negotiate oYG2MIGzo... Token here
Date: Tue, 18 Feb 2020 15:24:39 GMT
Content-Length: 295
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body>Body here</soap:Body></soap:Envelope>
Обновление: Вот исходный код клиента для вызова службы.
Программа:
class Program
{
static void Main(string[] args)
{
sendWebRequest();
}
static int _orderId = 1;
static int _mandant = 1;
static string _sId = "0123456789012345678901";
static string _isShipped = "eingeliefert";
static void sendWebRequest()
{
Console.WriteLine("Start webrequest Orderid: {0}, mandant: {1}, sId: {2}, isShipped: {3}", _orderId, _mandant, _sId, _isShipped);
WebserviceManager wm = new WebserviceManager();
wm.Open();
wm.SetStateToShipped(_orderId, _mandant, _sId, _isShipped);
wm.Close();
Console.WriteLine("Webrequest erfolgreich");
}
}
WebserviceManager:
public class WebserviceManager
{
protected MyContract.MyContractSoapClient _soapClient;
public WebserviceManager()
{
}
public void Open()
{
_soapClient = createWebServiceClient();
try
{
_soapClient.Open();
}
catch (Exception ex)
{
Logging.Error("Open", ex);
throw ex;
}
Logging.Info("_soap-Client open");
}
public void Close()
{
_soapClient.Close();
}
public void SetStateToShipped(int orderNo, int mandant, string sId, string isShipped)
{
_soapClient.DocumentShipped(orderNo, mandant, sId, isShipped);
}
protected MyContract.MyContractSoapClient createWebServiceClient()
{
return new MyContract.MyContractSoapSoapClient();
}
}