c# - ONVIF wsdl service: unable to authenticate -
i developing onvif driver using .net 4 (windows forms, not wcf). started importing wsdl files service in visual studio. able send command device in way:
httptransportbindingelement httptransportbindingelement = new httptransportbindingelement(); [...] textmessageencodingbindingelement messegeelement = new textmessageencodingbindingelement(); [...] custombinding binding = new custombinding(messegeelement, httptransportbindingelement); [...] endpointaddress serviceaddress = new endpointaddress(url); deviceclient deviceclient = new deviceclient(binding, serviceaddress); device channel = deviceclient.channelfactory.createchannel(); deviceservicecapabilities dsc = channel.getservicecapabilities();
but not able manage http digest authentication. spent days searching on google examples , solutions, ways seems hand write xml code. there not clean solution like:
deviceclient.channelfactory.credentials.httpdigest.clientcredential.username = username; deviceclient.channelfactory.credentials.httpdigest.clientcredential.password = digestpassword;
(that doesn't work)?
first of should install microsoft.web.services3 package. (view> other windows> package manager console). must add digest behavior endpoint. first part of code passworddigestbehavior class , after used connecting onvif device service.
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) { // 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) { // 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) { // nothing } public object beforesendrequest(ref system.servicemodel.channels.message request, system.servicemodel.iclientchannel channel) { // use 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 token xml xmldocument xmldoc = new xmldocument(); xmlelement securitytoken = token.getxml(xmldoc); // find nonce , add encodingtype attribute 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; } }
and how use it:
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);
Comments
Post a Comment