Onvif协议学习:7、鉴权认证

2023-10-27

Onvif协议学习:7、鉴权认证



原文链接:https://blog.csdn.net/benkaoya/article/details/72477536

1、前言

接着上一篇文章接续,上篇文章说到,在测试ONVIF标准的GetDeviceInformation接口时,有些IPC要求鉴权(认证),有些IPC不需要。其实总结起来应该是这样:

  • ONVIF规定,有些接口需要鉴权,有些接口不需要鉴权(在哪里查询等下会说明)。ONVIF规定GetDeviceInformation接口是需要鉴权的。

  • 市面上的IPC摄像头,特别是山寨货,并没有严格按ONVIF规范执行,造成对于有的IPC,客户端不携带鉴权信息也能成功调用GetDeviceInformation接口。

2、ONVIF哪些接口需要认证

辣么,问题来了,哪些ONVIF接口需要鉴权,哪些不需要鉴权,在哪里可以查看呢?答案是,在官网的ONVIF Core Specification文档中有详细的规定,如Version 16.12的版本为《ONVIF-Core-Specification-v1612.pdf》。在该文档的「Access classes for service requests」章节中有接口访问权限的相关规定,如下图所示。比如「PRE_AUTH」的规定是:The service shall not require user authentication,那非「PRE_AUTH」的就是都要认证的。

在这里插入图片描述

拿GetServices接口举个例子,在ONVIF Core Specification文档中找到GetServices接口定义(如下图所示),会有Access Class: PRE_AUTH的说明,表明客户端调用该接口时,不需要携带用户名、密码认证信息。

在这里插入图片描述

再看看GetDeviceInformation接口规定(如下图所示),Access Class: READ_SYSTEM,说明客户端调用该接口是需要进行认证。

在这里插入图片描述

3、如何认证

这里的鉴权信息包括用户名、密码,在HTTP传输过程中不能是明文,有一定的加密算法。

如果你整不清楚这个加密算法怎么回事,那么,我推荐利用gSOAP源码中的soap_wsse_add_UsernameTokenDigest函数,可以轻松实现鉴权。要使用该函数,需要注意以下几点:

  • 就像专栏前面文章提到过的一样,要使用soap_wsse_add_UsernameTokenDigest函数进行授权,在soapcpp2 生成ONVIF代码框架之前,要在onvif.h头文件开头加入:
#import “wsse.h”
  • 依赖gSOAP中的这些源码:wsseapi.c、wsseapi.h、mecevp.c、mecevp.h、smdevp.c、smdevp.h、threads.c、threads.h、dom.c,这些文件在gsoap目录和gsoap/plugin目录下,将这些文件拷贝到你的项目中,以便参与编译。

  • 在加入上面说的.c和.h文件后,结果编译失败,提示找不到「openssl/evp.h」文件:

smdevp.h(54): fatal error C1083: 无法打开包括文件:“openssl/evp.h”: No such file or directory

究其原因,wsse系列函数依赖OpenSSL库,我们得去OpenSSL官网下载源代码来编译、安装,里面有我们需要的库文件和头文件。

4、安装OpenSSL

如果你是跟着我专栏在学习,在专栏前面文章「使用gSOAP生成ONVIF框架代码」中,已经安装过OpenSSL了,对于还没安装OpenSSL的,可以参考那篇文章如何安装。

5、实现认证

代码如下,重点在ONVIF_SetAuthInfo函数(是对soap_wsse_add_UsernameTokenDigest的二次封装),相比于上一篇文章,这次的ONVIF_GetDeviceInformation函数内部,增加了设置鉴权信息,在调用soap_call___tds__GetDeviceInformation之前,先调用ONVIF_SetAuthInfo函数设置鉴权信息。

你可以拿一个需要鉴权的IPC来测试,通过开启、关闭ONVIF_SetAuthInfo语句,来观察效果。注意:你要是拿一个本就不需要鉴权的IPC,是测不出预期效果的。

#define USERNAME    "admin"
#define PASSWORD    "admin"

/************************************************************************
**函数:ONVIF_SetAuthInfo
**功能:设置认证信息
**参数:
        [in] soap     - soap环境变量
        [in] username - 用户名
        [in] password - 密码
**返回:
        0表明成功,非0表明失败
**备注:
************************************************************************/
static int ONVIF_SetAuthInfo(struct soap *soap, const char *username, const char *password)
{
    int result = 0;

    SOAP_ASSERT(NULL != username);
    SOAP_ASSERT(NULL != password);

    result = soap_wsse_add_UsernameTokenDigest(soap, NULL, username, password);
    SOAP_CHECK_ERROR(result, soap, "add_UsernameTokenDigest");

EXIT:

    return result;
}

/************************************************************************
**函数:ONVIF_GetDeviceInformation
**功能:获取设备基本信息
**参数:
        [in] DeviceXAddr - 设备服务地址
**返回:
        0表明成功,非0表明失败
**备注:
************************************************************************/
int ONVIF_GetDeviceInformation(const char *DeviceXAddr)
{
    int result = 0;
    struct soap *soap = NULL;
    struct _tds__GetDeviceInformation           devinfo_req;
    struct _tds__GetDeviceInformationResponse   devinfo_resp;

    SOAP_ASSERT(NULL != DeviceXAddr);
    SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));

    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);

    memset(&devinfo_req, 0x00, sizeof(devinfo_req));
    memset(&devinfo_resp, 0x00, sizeof(devinfo_resp));
    result = soap_call___tds__GetDeviceInformation(soap, DeviceXAddr, NULL, &devinfo_req, &devinfo_resp);
    SOAP_CHECK_ERROR(result, soap, "GetDeviceInformation");

    dump_tds__GetDeviceInformationResponse(&devinfo_resp);

EXIT:

    if (NULL != soap) {
        ONVIF_soap_delete(soap);
    }
    return result;
}

用大华IPC进行测试,执行结果如下:

================= + dump_tds__GetDeviceInformationResponse + >>>
Manufacturer:       Dahua
Model:              IPC-HDW1025C
Serial Number:      2K04788PAA00441
Hardware Id:        1.00
Firmware Version:   2.420.Dahua 00.14.R, build: 2016-06-18
================= - dump_tds__GetDeviceInformationResponse - <<<

6、特别注意

需要特别、特别、特别注意的是:但凡是ONVIF规定要鉴权的接口,每次调用之前,都要重新设置一次鉴权信息(即调用ONVIF_SetAuthInfo函数),哪怕你之前已经设置过鉴权信息了,否则后续调用ONVIF接口依然会报错。

我们来做个测试,连续两次调用soap_call___tds__GetDeviceInformation接口,第一次调用之前有设置鉴权信息,第二次调用之前没有设置鉴权信息,代码如下:

int ONVIF_GetDeviceInformation2(const char *DeviceXAddr)
{
    int result = 0;
    struct soap *soap = NULL;
    struct _tds__GetDeviceInformation           devinfo_req;
    struct _tds__GetDeviceInformationResponse   devinfo_resp;

    SOAP_ASSERT(NULL != DeviceXAddr);
    SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));

    /* 第一次调用soap_call___tds__GetDeviceInformation之前有设置鉴权信息 */
    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);

    memset(&devinfo_req, 0x00, sizeof(devinfo_req));
    memset(&devinfo_resp, 0x00, sizeof(devinfo_resp));
    result = soap_call___tds__GetDeviceInformation(soap, DeviceXAddr, NULL, &devinfo_req, &devinfo_resp);
    SOAP_CHECK_ERROR(result, soap, "GetDeviceInformation");
    dump_tds__GetDeviceInformationResponse(&devinfo_resp);


    /* 第二次调用soap_call___tds__GetDeviceInformation之前没有设置鉴权信息,导致调用失败 */
    memset(&devinfo_req, 0x00, sizeof(devinfo_req));
    memset(&devinfo_resp, 0x00, sizeof(devinfo_resp));
    result = soap_call___tds__GetDeviceInformation(soap, DeviceXAddr, NULL, &devinfo_req, &devinfo_resp);
    SOAP_CHECK_ERROR(result, soap, "GetDeviceInformation");
    dump_tds__GetDeviceInformationResponse(&devinfo_resp);

EXIT:

    if (NULL != soap) {
        ONVIF_soap_delete(soap);
    }
    return result;
}

同样用大华IPC进行测试,执行结果如下,第二次调用soap_call___tds__GetDeviceInformation失败:

================= + dump_tds__GetDeviceInformationResponse + >>>
Manufacturer:       Dahua
Model:              IPC-HDW1025C
Serial Number:      2K04788PAA00441
Hardware Id:        1.00
Firmware Version:   2.420.Dahua 00.14.R, build: 2016-06-18
================= - dump_tds__GetDeviceInformationResponse - <<<

[soap] GetDeviceInformation error: 401, is internal, HTTP Error

之所以会如此,究其根源,是因为IPC的应答信息会重置soap对象,导致鉴权信息丢失,所示每次都要重新设置鉴权信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Onvif协议学习:7、鉴权认证 的相关文章

  • ONVIF与RTSP的关系。

    先说结论 xff0c 个人觉得RTSP这个传输协议是ONVIF这个架构的部分功能 xff08 音视频流 xff09 的实现 也就是支持ONVIF的摄像头 xff0c 必定提供了RTSP视频流的接口 附 xff1a 海康威视RTSP的URL规
  • Onvif鉴权实现方式

    Onvif鉴权实现方式 Digest 61 B64ENCODE SHA1 B64DECODE Nonce 43 Date 43 Password gsoap中digest生成代码 xff1a int soap wsse add Userna
  • ONVIF对讲功能漫谈

    ONVIF对讲功能漫谈 前言 一 onvif对讲功能和onvif协议关系大吗 二 如何上报设备支持onvif对讲功能呢 三 onvif协议中哪个接口上报音频解码配置 四 献上抓包报文 前言 本篇文章尝试使用提问的方式来分享onvif对讲功能
  • Onvif协议学习:7、鉴权认证

    Onvif协议学习 7 鉴权认证 文章目录 Onvif协议学习 7 鉴权认证 1 前言 2 ONVIF哪些接口需要认证 3 如何认证 4 安装OpenSSL 5 实现认证 6 特别注意 原文链接 https blog csdn net be
  • WS-Discovery(网络服务动态发现)协议再解读

    WS Discovery 网络服务动态发现 协议再解读 文章目录 WS Discovery 网络服务动态发现 协议再解读 1 概述 2 协议资料 3 协议介绍 1 适用范围 2 不适用 4 协议示例及wireshark抓包分析 1 客户端探
  • go+gSoap+onvif学习总结:7、进行镜头调焦、聚焦和预置点的增删改查

    cgo gSoap onvif学习总结 7 进行镜头调焦 聚焦和预置点的增删改查 文章目录 cgo gSoap onvif学习总结 7 进行镜头调焦 聚焦和预置点的增删改查 1 前言 2 gSoap生成c代码框架 3 完成c代码实例并测试
  • ONVIF测试工具 ONVIF Device Test Tool的使用

    ONVIF测试工具 ONVIF Device Test Tool的使用 双击 打开软件 选择当前网络 点击 Discover Devices 进行搜索 可以看到搜索到一个设备
  • gsoap学习笔记一

    本文章是对gsoap中生成的cpp类型的代码框架的应用 因为要实现一些ONVIF规范中的一些功能 所以选择了gsoap生成代码框架 但是发现好多博客上都是生成的C的代码框架 使用起来很麻烦 而且引用插件功能的时候 什么时候需要修改文件内容
  • Onvif协议学习:8、设备校时

    Onvif协议学习 8 设备校时 文章目录 Onvif协议学习 8 设备校时 1 编码流程 2 注意事项 3 示例代码 原文链接 https blog csdn net benkaoya article details 72486511 1
  • Go语言实现Onvif服务端:1、提供网络发现服务

    Go语言实现Onvif服务端 1 提供网络发现服务 文章目录 Go语言实现Onvif服务端 1 提供网络发现服务 1 前言 2 代码 3 结果 1 前言 该功能我们之前学习Onvif协议和WS Discovery时已经有了一定的基础了 接下
  • Go语言实现Onvif客户端:6、获取rtsp流地址

    Go语言实现Onvif客户端 6 获取rtsp流地址 文章目录 Go语言实现Onvif客户端 6 获取rtsp流地址 1 代码 2 结果 3 查看 1 代码 获取并选择Profile token后获取rtsp流地址也是调用接口即可 Desc
  • Go语言实现Onvif客户端:7、获取摄像头快照

    Go语言实现Onvif客户端 7 获取摄像头快照 文章目录 Go语言实现Onvif客户端 7 获取摄像头快照 1 代码 2 结果 3 查看 1 代码 摄像头对该时刻可以进行快照抓拍 抓拍结果可以以url地址的形式提供 在浏览器上可以直接查看
  • cgo+gSoap+onvif学习总结:1、方案初衷、资料收集及cgo实现helloworld

    cgo gSoap onvif学习总结 1 方案初衷 资料收集及cgo实现helloworld 文章目录 cgo gSoap onvif学习总结 1 方案初衷 资料收集及cgo实现helloworld 1 前言 2 资料收集 3 cgo h
  • Go语言实现Onvif客户端:2、获取设备信息

    Go语言实现Onvif客户端 2 获取设备信息 文章目录 Go语言实现Onvif客户端 2 获取设备信息 1 思路 2 代码 1 思路 搜索设备 获取设备能力 通过设备能力的设备接口读取设备信息 我们上节说了 主要是通过设备信息中的内容来区
  • Onvif协议学习:12、修改分辨率

    Onvif协议学习 12 修改分辨率 文章目录 Onvif协议学习 12 修改分辨率 1 原理简介 2 函数接口 3 编码流程 4 示例代码 原文链接 https blog csdn net benkaoya article details
  • C# 中的 Onvif 事件订阅

    我正在用 C 实现 ipCamera 编码器管理系统 该系统将管理来自多个供应商的多个 ipCamera 和 或编码器 使用 Onvif 代替每个 ipcamera 或编码器 sdk 将是一个好处 管理系统的关键概念之一是监听来自摄像机的事
  • 无法使用 C# 连接到启用 OnVif 的相机

    我是第一次使用 IPCam 并尝试连接到 OnVif 摄像机 我查看了各种论坛和堆栈溢出 并提出了以下代码 我知道该代码没有做任何有用的事情 但它现在只是一个概念证明 它找到我网络上的所有 4 个摄像头 然后我手动连接到其中一个摄像头以拉回
  • ONVIF 获取系统日期和时间请求

    一旦我从 UDP 多播请求返回 239 255 255 250 的响应 我返回带有 XAddrs 的 ProbeMatchhttp 10 10 10 10 1234 onvif device service 我现在如何执行 GetSyste
  • 基于ONVIF wsdl生成Java webservice(自顶向下方法)

    我想为像相机这样的设备生成服务器代码 这些设备有一个标准协议 称为ONVIF https www onvif org它发布了一些流行的 WSDL 文档 所以我必须从 ONFIV 的 WSDL 文档生成一个接口和骨架 当我使用 wsdl2ja
  • Onvif - 尝试了解它是如何工作的

    首先 我完全没有使用ONVIF的经验 我在一家公司获得了奖学金 并被要求与它一起工作 控制一些相机并从它们那里获取照片 但他们也不知道它是如何工作的 所以没有人可以帮助我很多 我正在阅读 ONVIF 网页上提供的规范 但我不太明白 我知道我

随机推荐

  • Rxjava参考文档

    https mcxiaoke gitbooks io rxdocs content operators Timer html
  • lua动态链接库(luaopen_*函数的使用)

    lua中使用c动态库 像luacjson 支持unicode luasocket 都是以动态链接库的形式在lua中使用的 至于怎么写这些动态链接库很少有教程说到 下面我就说说如何把c文件编译成动态库 首先 假设需要在lua中调用一个在c中实
  • 第二章 组合逻辑设计

    第二章 组合逻辑设计 1 卡诺图化简 1 1 必须是偶数项化简 因为卡诺图只有相邻格可以消除一个项 1 2 积之和形式的化简 消除相邻的1项 得到f 1 3 和之积形式的化简 消除相邻的0项 得到f 的积之和形式 然后再通过狄摩根定律转换成
  • python 按照行取平均值补齐缺失数据

    import pandas as pd 根据行来求平均值 def fill NAN filePath r E study python 0819 filled meter 500 csv df0 pd read csv filePath e
  • 线程池参数配置与Linux CPU

    1 线程池核心线程数配置 1 核心线程计算 计算密集型 cpu的个数 1 IO密集型 2 cpu个数 1 2 linux查看cpu核数 查看物理CPU个数 cat proc cpuinfo grep physical id sort uni
  • Educoder--Java高级特性 - 多线程基础(2)常用函数

    注意啦 这期的复制又恢复正常了 第一题 有三种原因可以导致线程不能运行 它们是 A 等待 B 阻塞 C 休眠 D 挂起及由于I O操作而阻塞 Java语言中提供了一个 线程 自动回收动态分配的内存 A 异步 B 消费者 C 守护 D 垃圾收
  • 字符串截取大全

    C 几个经常用到的字符串的截取 string str 123abc456 int i 3 1 取字符串的前i个字符 str str Substring 0 i or str str Remove i str Length i 2 去掉字符串
  • [C语言]猜数字

    本文章为c语言猜数字小游戏的教学 设计思路 目录 1 菜单的创建 2 猜数字的实现 3 完整代码 1 菜单的创建 先设计一个类似菜单的界面 供选择来实现游戏或退出 void menu printf n printf 猜数字 n printf
  • iTween基础之Look(使对象面朝指定位置)

    一 基础介绍 二 基础属性 原文地址 http blog csdn net dingkun520wy article details 50578142 一 基础介绍
  • 【Java基础】关于语言:编译型与解释型

    编译型 一 定义 使用专门的编译器 针对特定的平台 将高级语言源代码一次性的编译成可被该平台硬件执行的机器码 并包装成该平台所能识别的可执行性程序的格式 二 特点 程序执行前需要专门的一个编译过程 将源代码编译成机器语言 如 exe后缀的文
  • Python调用sort函数自定义排序函数

    当有一组比较复杂的对象需要进行排序时 我们的第一想法就是尽量利用已有的函数快速完成自己的排序需求 接触过c 的码友应该知道 在c 里若想利用已有的sort函数来完成复杂的排序 对运算符进行重载即可 好久没接触过c 里的概念 应该是这个叫法
  • java项目连接mysql卡死_我的Java连接数据库之后就卡住了 不能输出结果 到底是为什么呢?程序的功能是要完成一个地址的最大正向查...

    以下是基本的函数实现最重要的是第四个要实现街道的最大正向查找 ResultSetrs s executeQuery sql if rs next Stringpostaddress rs getString 1 Joutput setTex
  • 用Python开始机器学习(5:文本特征抽取与向量化)

    假设我们刚看完诺兰的大片 星际穿越 设想如何让机器来自动分析各位观众对电影的评价到底是 赞 positive 还是 踩 negative 呢 这类问题就属于情感分析问题 这类问题处理的第一步 就是将文本转换为特征 因此 这章我们只学习第一步
  • Hyperledger Fabric 应用实战(3)--配置文件core.yaml

    1 简介 core yaml主要是为Peer服务提供一些配置定义 当Peer节点启动时 会先从命令行获取参数 环境变量 和core yaml读取配置信息 通过docker去搭建一个Peer服务 命令行默认是不带参数的 主要通过docker
  • 考研 打赢这场信息站 上岸

    23考研已经结束了 新的考研马上开始 考研 是一个 持久战 也是一个 信息战 因为大多数同学都是自我监督 自我学习 所以经常出现想要摆烂 放弃的念头 意念坚定的同学只占一小部分 这个时候我们就要先在考研之前进行问题分析 这是一个非常非常重要
  • Spark Streaming入门

    什么是Spark Streaming 首先 什么是流 streaming 数据流是连续到达的无穷序列 流处理将不断流动的输入数据分成独立的单元进行处理 流处理是对流数据的低延迟处理和分析 Spark Streaming是Spark API核
  • openssl常用参数

    文章目录 前言 对称加密 标准语法 常用选项 应用示例 单向加密 标准语法 常用选项 应用示例 参考文档 前言 OpenSSL 是一个开源项目 可以实现 秘钥证书管理 对称加密和非对称加密 其主要由一下三个组件组成 openssl 多用途的
  • Synchronized与锁升级

    目录 1 先从阿里及其他大厂面试题说起 2 路线总纲 3 Synchronized的性能变化 4 Synchronized锁种类及升级步骤 4 1多线程访问情况 3种 4 2升级流程 4 3无锁 4 4偏向锁 4 5轻量级锁 4 6重量级锁
  • 【经典】springboot 配置文件统一管理

    背景 为实现快速搭建和开发 项目以Springboot框架搭建 springboot搭建的项目可以将项目直接打成jar包并运行 无需自己安装配置Tomcat或者其他服务器 是一种方便快捷的部署方式 假设项目以最常规的方式打包成一个整体的ja
  • Onvif协议学习:7、鉴权认证

    Onvif协议学习 7 鉴权认证 文章目录 Onvif协议学习 7 鉴权认证 1 前言 2 ONVIF哪些接口需要认证 3 如何认证 4 安装OpenSSL 5 实现认证 6 特别注意 原文链接 https blog csdn net be