You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ONVIF认证开发疑问:VB.NET下WS-Security及HTTP摘要认证求助

关于ONVIF认证在VB.NET中的实现方案

我完全懂你说的这种头疼的感觉——ONVIF的WS-Security认证确实是个绕不开的坎,尤其是在VB.NET环境下找能用的示例简直像大海捞针。下面针对你的问题逐一解答:

1. HTTP摘要认证 vs WS-Security的适用性

ONVIF标准主要依赖WS-Security的UsernameToken Profile(带密码摘要的版本),而HTTP摘要认证是HTTP层级的认证机制,虽然部分ONVIF设备可能支持,但并非所有设备都兼容,而且不符合ONVIF的标准规范。所以如果要保证兼容性,还是得实现WS-Security的认证逻辑。

2. VB.NET移植C#认证示例的可行性

当然有开发者完成过这项工作!核心思路和C#一致:手动构造SOAP消息中的<Security>头部,包含UsernameToken、随机Nonce、Created时间戳,以及基于Nonce + Created + 密码计算的SHA1摘要。

这里给你一个简化的VB.NET代码片段,用来生成WS-Security头部并注入到WCF请求中:

自定义消息检查器(注入WS-Security头)

Imports System
Imports System.ServiceModel
Imports System.ServiceModel.Dispatcher
Imports System.Security.Cryptography
Imports System.Text

Public Class OnvifSecurityInspector
    Implements IClientMessageInspector

    Private ReadOnly _username As String
    Private ReadOnly _password As String

    Public Sub New(username As String, password As String)
        _username = username
        _password = password
    End Sub

    ' 处理回复(这里不需要额外操作)
    Public Sub AfterReceiveReply(ByRef reply As Message, correlationState As Object) Implements IClientMessageInspector.AfterReceiveReply
    End Sub

    ' 发送请求前注入Security头
    Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
        ' 生成随机Nonce和UTC时间戳
        Dim nonceBytes As Byte() = New Byte(15) {}
        Using rng As New RNGCryptoServiceProvider()
            rng.GetBytes(nonceBytes)
        End Using
        Dim nonceBase64 = Convert.ToBase64String(nonceBytes)
        Dim createdTimestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")

        ' 计算密码摘要:SHA1(Nonce + Created + 原始密码)
        Dim digestInput = nonceBase64 & createdTimestamp & _password
        Dim digestBytes = New SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(digestInput))
        Dim passwordDigest = Convert.ToBase64String(digestBytes)

        ' 构造SOAP Security头部XML
        Dim securityXml = $"<wsse:Security xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"">
                                <wsse:UsernameToken>
                                    <wsse:Username>{_username}</wsse:Username>
                                    <wsse:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"">{passwordDigest}</wsse:Password>
                                    <wsse:Nonce EncodingType=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"">{nonceBase64}</wsse:Nonce>
                                    <wsu:Created xmlns:wsu=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"">{createdTimestamp}</wsu:Created>
                                </wsse:UsernameToken>
                            </wsse:Security>"

        ' 将XML转换为MessageHeader并添加到请求中
        Dim securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityXml, False)
        request.Headers.Add(securityHeader)

        Return Nothing
    End Function
End Class

' 自定义行为类,用来添加消息检查器
Public Class OnvifClientBehavior
    Implements IEndpointBehavior

    Public ReadOnly Property MessageInspectors As New List(Of IClientMessageInspector)()

    Public Sub AddBindingParameters(endpoint As ServiceEndpoint, bindingParameters As BindingParameterCollection) Implements IEndpointBehavior.AddBindingParameters
    End Sub

    Public Sub ApplyClientBehavior(endpoint As ServiceEndpoint, clientRuntime As ClientRuntime) Implements IEndpointBehavior.ApplyClientBehavior
        For Each inspector In MessageInspectors
            clientRuntime.ClientMessageInspectors.Add(inspector)
        Next
    End Sub

    Public Sub ApplyDispatchBehavior(endpoint As ServiceEndpoint, endpointDispatcher As EndpointDispatcher) Implements IEndpointBehavior.ApplyDispatchBehavior
    End Sub

    Public Sub Validate(endpoint As ServiceEndpoint) Implements IEndpointBehavior.Validate
    End Sub
End Class

使用示例

' 假设你已经通过ONVIF的WSDL生成了VB.NET客户端(比如OnvifMediaClient)
Dim mediaClient As New OnvifMediaClient()
Dim securityBehavior As New OnvifClientBehavior()
' 添加认证检查器,替换为你的设备用户名和密码
securityBehavior.MessageInspectors.Add(New OnvifSecurityInspector("admin", "your_device_password"))
mediaClient.Endpoint.Behaviors.Add(securityBehavior)

' 接下来就可以正常调用ONVIF接口了
Dim profiles = mediaClient.GetProfiles()

3. 现成的DLL或封装服务

目前没有官方提供的带WS-Security的VB.NET ONVIF库,但有不少开源项目可以参考:

  • 一些开发者会把C#的ONVIF客户端库(比如ONVIF-Device-Manager的核心逻辑)移植到VB.NET,你可以搜索VB.NET ONVIF相关的开源仓库,找到已经封装好WS-Security的实现
  • 也可以使用WCF的ChannelFactory结合上述消息检查器的方式,不需要额外的DLL,纯代码实现认证逻辑

4. 找不到VB.NET示例的原因

确实,VB.NET的ONVIF资源远少于C#,因为大部分开源项目和官方示例都优先用C#。但只要掌握了WS-Security的核心逻辑,移植C#代码到VB.NET是完全可行的——两者的WCF操作逻辑一致,只是语法有差异,重点是构造正确的SOAP Security头部。

内容的提问来源于stack exchange,提问作者Richard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:16:07