这个问题在这里已经讨论过几个话题,但我找不到答案。
我想做的是通过Onvif接口使用IP摄像头。我从Onvif主页中的WSDL文件中生成了web服务,并按照建议的这里添加了自定义SOAP身份验证代码,并且能够检索设备功能等等。
但是对于某些服务,例如PTZ控件,也需要HTTP身份验证。我的代码删除了ClientCredentials行为(因此,我想设置它们没有任何意义,但我仍然保留了这些行,希望HTTPTransport会尝试使用它们):
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的第一次体验,到目前为止,我已经做了所有的工作,从互联网上找到的例子,但关于这个特定的问题,我还没有找到任何东西。
发布于 2014-02-28 13:18:13
如果有人感兴趣的话,我就是这么做的。我以以下方式将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)身份验证级别上都能工作。
发布于 2014-02-28 07:36:13
我详细介绍了HTTP摘要在另一个回答中是如何工作的。
请记住,根据PRE_AUTH的5.12.1节,只有类岩心规格的函数需要身份验证。
您应该调用除PRE_AUTH之外的任何类的函数,而不需要任何形式的身份验证。如果您得到一个HTTP 401,那么您必须使用HTTP,否则您将不得不使用with。
您不能直接使用HTTP摘要,因为您至少需要该设备向您发送HTTP摘要的质询。
https://stackoverflow.com/questions/21170475
复制相似问题