首先,你应该安装Microsoft.Web.Services3包。 (查看>其他窗口>程序包管理器控制台)。然后,您必须将摘要行为添加到您的端点。代码的第一部分是PasswordDigestBehavior类,之后用于连接到ONVIF设备服务。
public class PasswordDigestBehavior : IEndpointBehavior
{
public String Username { get; set; }
public String Password { get; set; }
public PasswordDigestBehavior(String username, String password)
{
this.Username = username;
this.Password = password;
}
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
// do nothing
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
//clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));
clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
throw new NotImplementedException();
}
public void Validate(ServiceEndpoint endpoint)
{
// do nothing...
}
}
public class PasswordDigestMessageInspector : IClientMessageInspector
{
public String Username { get; set; }
public String Password { get; set; }
public PasswordDigestMessageInspector(String username, String password)
{
this.Username = username;
this.Password = password;
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
// do nothing
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
// Use the WSE 3.0 security token class
var option = PasswordOption.SendHashed;
if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password))
option = PasswordOption.SendPlainText;
UsernameToken token = new UsernameToken(this.Username, this.Password, option);
// Serialize the token to XML
XmlDocument xmlDoc = new XmlDocument();
XmlElement securityToken = token.GetXml(xmlDoc);
// find nonce and add EncodingType attribute for BSP compliance
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsMgr.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
XmlNodeList nonces = securityToken.SelectNodes("//wsse:Nonce", nsMgr);
XmlAttribute encodingAttr = xmlDoc.CreateAttribute("EncodingType");
encodingAttr.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary";
if (nonces.Count > 0)
{
nonces[0].Attributes.Append(encodingAttr);
//nonces[0].Attributes[0].Value = "foo";
}
//
MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityToken, false);
request.Headers.Add(securityHeader);
// complete
return Convert.DBNull;
}
}
这是如何使用它:
var endPointAddress = new EndpointAddress("http://DEVICE_IPADDRESS/onvif/device_service");
var httpTransportBinding = new HttpTransportBindingElement { AuthenticationScheme = AuthenticationSchemes.Digest };
var textMessageEncodingBinding = new TextMessageEncodingBindingElement { MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None) };
var customBinding = new CustomBinding(textMessageEncodingBinding, httpTransportBinding);
var passwordDigestBehavior = new PasswordDigestBehavior(USERNAME, PASSWORD);
var deviceService = new DeviceClient(customBinding, endPointAddress);
deviceService.Endpoint.Behaviors.Add(passwordDigestBehavior);
很多东西都是从你的榜样缺失,和一些非常重要的东西......你怎么了用于格式化摘要头部的变量? (?例如现时你需要做出一个请求?) – cube45
是的,你是对的:你必须发送一个请求,无需认证,服务器将包含随机数,境界等的错误信息回答。 – ElmoDev001
你是否在BeforeSendRequest的开头创建了自己的HttpClient?你能编辑你的答案并提供一个更完整的例子吗? http://findnerd.com/list/view/How-to-resolve-Http-400-Bad-Request-while-authenticating-with-ONVIF-camera/: – cube45