2014-01-16 82 views
0

这个问题已经在几个主题中讨论过了,但是我找不到答案。带有SOAP级别认证和HTTP认证的Onvif SOAP请求

我想要做的是通过Onvif接口使用IP摄像机。我从Onvif主页中的WSDL文件生成了Web服务,并添加了建议的here的自定义SOAP验证代码,并且我能够检索设备功能等等。

但是对于某些服务,例如PTZ控制,还需要HTTP认证。我的代码删除ClientCredentials behaivor(所以是的,我想将它们设置没有任何意义,但我仍然留在希望,也许HTTP传输将尝试使用它们的那些行):

HttpTransportBindingElement httpBindingElement = new HttpTransportBindingElement(); 
httpBindingElement.AuthenticationScheme = AuthenticationSchemes.Basic; 
... 
PTZClient ptzClient = new PTZClient(customBinding, endPointAddress); 
ptzClient.Endpoint.Behaviors.Remove(typeof(System.ServiceModel.Description.ClientCredentials)); 
UsernameClientCredentials onvifCredentials = new UsernameClientCredentials(new UsernameInfo(_username, _password)); 
ptzClient.Endpoint.Behaviors.Add(onvifCredentials); 
ptzClient.ClientCredentials.UserName.UserName = _username; 
ptzClient.ClientCredentials.UserName.Password = _password; 

不过,当我看看wireshark,我发现生成了SOAP身份验证,但没有设置HTTP身份验证头(呃,我已经预料到了,因为我在这里有一个自定义的行为)。所以问题是,如果我以这种方式创建绑定,那么添加HTTP身份验证头文件的最佳选择是什么?我可以只添加一个消息检查器,如果有的话,任何示例?我必须创建一个不同的传输绑定?我见过有人建议其他人使用BasicHttpBinding,然后设置Security属性,但是在这种情况下,证书的位置在哪里?我如何将BasicHttpBinding实例应用于我的绑定?是否有任何回调在WCF中被HTTP 401代码触发,我可以连接并提供头文件?这实际上是我第一次使用WCF,到目前为止,我已经完成了从互联网上找到的所有例子,但是对于这个特殊的问题,我一直无法找到任何东西。

回答

1

如果有人有兴趣,这是我如何得到它的工作。我结合BasicHttpBinding在接下来的方式,客户端凭证:

TransportSecurityBindingElement transportSecurity = new TransportSecurityBindingElement(); 
// UsernameCredentials is a class implementing WS-UsernameToken authentication 
transportSecurity.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UsernameTokenParameters()); 
transportSecurity.AllowInsecureTransport = true; 
transportSecurity.IncludeTimestamp = false; 
TextMessageEncodingBindingElement messageEncoding = new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8); 
HttpClientCredentialType[] credentialTypes = new HttpClientCredentialType[3] { HttpClientCredentialType.None, HttpClientCredentialType.Basic, HttpClientCredentialType.Digest }; 
... 
foreach (HttpClientCredentialType credentialType in credentialTypes) 
{ 
    BasicHttpBinding httpBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly); 
    httpBinding.Security.Transport.ClientCredentialType = credentialType; 
    BindingElementCollection elements = new BindingElementCollection(new BindingElement[1]{messageEncoding}); 
    foreach(BindingElement element in httpBinding.CreateBindingElements()) 
    { 
     if (element is TextMessageEncodingBindingElement) 
      continue; 
     elements.Add(element); 
    } 
    CustomBinding customBinding = new CustomBinding(elements); 
    DeviceClient deviceClient = new DeviceClient(customBinding, endPointAddress); 
    if (credentialType == HttpClientCredentialType.Basic) 
    { 
     // Set all credentials, not sure from which one WCF actually takes the value 
     deviceClient.ClientCredentials.UserName.UserName = pair[0]; 
     deviceClient.ClientCredentials.UserName.Password = pair[1]; 
    } 
    else if (credentialType == HttpClientCredentialType.Digest) 
    { 
     deviceClient.ClientCredentials.HttpDigest.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation; 
     deviceClient.ClientCredentials.HttpDigest.ClientCredential.UserName = pair[0]; 
     deviceClient.ClientCredentials.HttpDigest.ClientCredential.Password = pair[1]; 
    } 
} 

这与我们不知道的认证模式和认证工作在两个(HTTP/SOAP)身份验证级别的设备高效地工作。

0

我详细介绍了HTTP摘要如何在另一个answer中工作。

请记住,根据Core spec的§5.12.1,只有类PRE_AUTH的功能需要验证。

您应该调用任何类的函数,但PRE_AUTH没有任何表单身份验证。如果你得到一个HTTP 401那么你必须使用HTTP digset,否则你将不得不使用WS-UsernameToken。

不能直接使用HTTP消化,因为你至少需要设备向您发送challange的HTTP摘要。

+0

我同意,但问题是,在给出的代码示例中,即使从服务器返回HTTP验证标头,连接也不会重试,而只是失败。 –