【问题标题】:Onvif SOAP request with SOAP level authentication and HTTP authenticationOnvif SOAP 请求,带有 SOAP 级别身份验证和 HTTP 身份验证
【发布时间】:2014-01-16 18:57:43
【问题描述】:

这个问题已经在这里的几个主题中讨论过,但我找不到适合我的答案。

我正在尝试通过 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 的第一次体验,到目前为止,我已经完成了从互联网上找到的示例的所有内容,但是对于这个特定的问题,我还没有找到任何东西。

【问题讨论】:

    标签: c# wcf soap onvif


    【解决方案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) 身份验证级别上工作。

    【讨论】:

      【解决方案2】:

      我在另一个 answer 中详细介绍了 HTTP 摘要的工作原理。

      请记住,根据Core spec 的§5.12.1,只有PRE_AUTH 类的函数需要身份验证。

      您应该调用除 PRE_AUTH 之外的任何类的函数,而无需任何表单身份验证。如果你得到HTTP 401,那么你必须使用 HTTP digset,否则你必须使用 WS-UsernameToken。

      您不能直接使用 HTTP 摘要,因为您至少需要设备向您发送 HTTP 摘要挑战。

      【讨论】:

      • 我同意,但问题在于给出的代码示例,即使从服务器返回 HTTP 身份验证标头,连接也不会重试响应而只是失败。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多