The main point while authenticating with Onvif camera using Onvif wsdl is to create our custom behavior class and pass the camera credentials using that class. Here, below is the code for custom behavior class.
Adding namespace:
using System.ServiceModel.Description;
using Microsoft.Web.Services2.Security.Tokens;
using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Xml;
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;
}
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
#endregion
}
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 Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
UsernameToken token = new UsernameToken(this.Username, this.Password, PasswordOption.SendHashed);
// 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);
}
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;
}
}
After creating PasswordDigestBehavior class, simply add the given below code. Here below is the example of Media service in Onvif wsdl.
ServicePointManager.Expect100Continue = false;
// using this endpoint url "http://ONVIF-IP-ADDRESS/onvif/services" , we can call deviceIO, devicemanagement and media services in Onvif wsdl
EndpointAddress endPointAddress = new EndpointAddress("http://" + "ONVIF-IP-ADDRESS" + "/onvif/services");
HttpTransportBindingElement httpTransportBinding = new HttpTransportBindingElement { AuthenticationScheme = AuthenticationSchemes.Digest };
TextMessageEncodingBindingElement textMessageEncodingBinding = new TextMessageEncodingBindingElement { MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None) };
CustomBinding customBinding = new CustomBinding(textMessageEncodingBinding, httpTransportBinding);
//Pass camera username and password without any conversion
PasswordDigestBehavior passwordDigestBehavior = new PasswordDigestBehavior("username", "password"); //Use our custom behaviour class that I created above
MediaClient mediaClient = new MediaClient(customBinding, endPointAddress);
mediaClient.Endpoint.Behaviors.Add(passwordDigestBehavior);
Profile[] profs = mediaClient.GetProfiles();
Profile profile = mediaClient.GetProfile(profs[0].token);
Hope this code will help you. Thanks.
0 Comment(s)