먼저 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);
예제에서 많은 것들이 누락되었습니다. 그리고 매우 중요한 몇 가지 사항 ... 다이제스트 헤더의 형식을 지정하는 데 사용되는 변수를 어떻게 얻습니까? (예 : nonce? 요청을해야합니까?) – cube45
맞습니다. 인증없이 요청을 보내면 서버는 nonce, 영역 등을 포함하는 오류 메시지로 응답합니다. – ElmoDev001
BeforeSendRequest 시작 부분에 HttpClient를 만들고 있습니까? 답을 편집하고보다 완벽한 예를 제공해 주시겠습니까? – cube45