【发布时间】:2020-07-12 03:04:46
【问题描述】:
我有一个向 SOAP 服务发送简单 Web 请求的客户端。它是一个简单的 C# 程序,它使用服务的 WSDL 文件来创建客户端。该服务托管在 IIS 8.5 和 Windows Server 2012 上。它在使用匿名身份验证时工作正常,但在 Windows 身份验证时会失败。客户端和服务都在同一个域中,用户权限也可以。
我配置了 IIS,使其禁用除 Windows 身份验证(协商、NTLM)之外的所有形式的身份验证。客户端已配置为使用 Windows 作为客户端凭据类型。
当我发送请求时,我收到以下错误: “HTTP 请求未使用客户端身份验证方案‘协商’。从服务器收到的身份验证标头是‘协商,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();
}
}
【问题讨论】:
-
能否提供您的客户端源代码?
-
@OguzOzgul 我编辑了帖子以包含客户端源代码。
-
您能否检查一下clientCredentialType属性here。将其设置为 Ntlm 可能会有所帮助。
-
@OguzOzgul 不幸的是,这也没有成功。来自服务器的类似响应,但未成功。
-
很抱歉加热它。是否可以共享服务端点?
标签: c# asp.net web-services soap windows-authentication