这个问题已经在几个主题中进行了讨论,但我无法找到答案。
我要做的是通过Onvif界面使用IP摄像头。我已经从Onvif主页上提供的WSDL文件生成了Web服务,并按照建议here添加了自定义SOAP身份验证代码,并且我能够检索设备功能等等。
但对于某些服务,例如PTZ控制,还需要HTTP身份验证。我的代码删除了ClientCredentials
行为(所以是的,我想设置它们没有任何意义,但我仍然希望这些行可能会使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,到目前为止,我已经完成了互联网上的所有示例,但至于这个特殊问题我还没有找到任何东西。
答案 0 :(得分:2)
如果有人有兴趣,我就是这样做的。我以下列方式将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)身份验证级别。
答案 1 :(得分:0)