嗨,我有一个简单的客户端:
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Ntlm
{
public class Program
{
#region Methods
private static void Main()
{
var t = new Program();
Console.WriteLine("Starting....");
t.Run();
}
private void Run()
{
// First procedure:
// create a WSHttpBinding that uses Windows credentials and message security
var myBinding = new WSHttpBinding
{
Security =
{
Mode = SecurityMode.Message, Message = {ClientCredentialType = MessageCredentialType.Windows}
}
};
// 2nd Procedure:
// Use the binding in a service
// Create the Type instances for later use and the URI for
// the base address.
var contractType = typeof(ICalculator);
var serviceType = typeof(Calculator);
var baseAddress = new Uri("http://localhost:8036/SecuritySamples");
// Create the ServiceHost and add an endpoint, then start
// the service.
var myServiceHost = new ServiceHost(serviceType, baseAddress);
myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator");
//enable metadata
var smb = new ServiceMetadataBehavior {HttpGetEnabled = true};
myServiceHost.Description.Behaviors.Add(smb);
myServiceHost.Open();
Console.WriteLine("Listening");
Console.WriteLine("Press Enter to close the service");
Console.ReadLine();
myServiceHost.Close();
}
#endregion
}
[ServiceContract]
public interface ICalculator
{
#region Public Methods and Operators
[OperationContract]
double Add(double a, double b);
#endregion
}
public class Calculator : ICalculator
{
#region Public Methods and Operators
public double Add(double a, double b)
{
return a + b;
}
#endregion
}
}
,在app.config中,只有system.diagnostics
现在,我正在尝试发送
HttpWebRequest
以获得此服务的响应。 Wcf测试客户端当然可以做到这一点,它会在扫描服务时使用此服务对自己进行身份验证,然后发送如下请求:
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/ICalculator/Add</a:Action>
<a:MessageID>urn:uuid:dcac8c1e-b552-4011-8cf6-a0d3829aec71</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
</s:Header>
<s:Body>
<Add xmlns="http://tempuri.org/">
<a>0</a>
<b>0</b>
</Add>
</s:Body>
</s:Envelope>
现在:根据我发送的内容,我使用NTLM身份验证会得到不同的结果
情况1:
我发送了请求
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<Add xmlns="http://tempuri.org/">
<a>1</a>
<b>1</b>
</Add>
</s:Body>
</s:Envelope>
带有标题
Content-Type application / soap + xml; charset = utf-8; action =“ http://tempuri.org/ICalculator/Add”
我收到一个400错误的请求,这是我发送的方式:
var req = WebRequest.CreateHttp(m.GetUri());
req.Timeout = Timeout;
req.AllowAutoRedirect = m.AutoRedirect;
req.Method = "Post";
req.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
req.Credentials = new CredentialCache {
{ Destination.Host, Destination.Port, "NTLM", new NetworkCredential(Config.Username, Config.Password, Config.AuthenticationDomain) },
};
req.Proxy.Credentials = request.Credentials;
req.ContentType = "application/soap+xml;charset=utf-8;action=\"http://tempuri.org/ICalculator/Add\""
案例2:我发送了有效载荷
<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"><Header xmlns="http://www.w3.org/2003/05/soap-envelope"><Action xmlns="http://www.w3.org/2005/08/addressing">http://tempuri.org/ICalculator/Add</Action></Header>
<s:Body>
<Add xmlns="http://tempuri.org/">
<a>1</a>
<b>1</b>
</Add>
</s:Body>
</s:Envelope>
具有与上述相同的设置,并且出现500内部服务器错误
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Sender</s:Value>
<s:Subcode>
<s:Value xmlns:a="http://schemas.xmlsoap.org/ws/2005/02/sc">a:BadContextToken</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="de-AT">The message could not be processed. This is most likely because the action 'http://tempuri.org/ICalculator/Add' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.</s:Text>
</s:Reason>
</s:Fault>
</s:Body>
</s:Envelope>
在分析了WCF日志,提琴手和Wireshark之后,我看到该消息在我的情况下是裸发送的,挑战没有以某种方式到达,并且我的代码没有401。问题是什么? Kerberos也有同样的问题