ONVIF协议网络摄像机(IPC)客户端程序开发(9):鉴权(认证)
1 专栏导读
本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解,专栏前面文章讲过的知识点(或代码段),后面文章不会赘述。为了节省篇幅,突出重点,在文章中展示的示例代码仅仅是关键代码,你可以在「专栏开篇」中获取完整代码。
如有错误,欢迎你的留言纠正!让我们共同成长!你的「点赞」或「打赏」是对我最大的支持和鼓励!
2 前言
接着上一篇文章接续,上篇文章说到,在测试ONVIF标准的GetDeviceInformation接口时,有些IPC要求鉴权(认证),有些IPC不需要。其实总结起来应该是这样:
ONVIF规定,有些接口需要鉴权,有些接口不需要鉴权(在哪里查询等下会说明)。ONVIF规定GetDeviceInformation接口是需要鉴权的。
市面上的IPC摄像头,特别是山寨货,并没有严格按ONVIF规范执行,造成对于有的IPC,客户端不携带鉴权信息也能成功调用GetDeviceInformation接口。
3 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,说明客户端调用该接口是需要进行认证。
4 如何认证
这里的鉴权信息包括用户名、密码,在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官网下载源代码来编译、安装,里面有我们需要的库文件和头文件。
5 安装OpenSSL
如果你是跟着我专栏在学习,在专栏前面文章「使用gSOAP生成ONVIF框架代码」中,已经安装过OpenSSL了,对于还没安装OpenSSL的,可以参考那篇文章如何安装。
6 实现认证
代码如下,重点在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 - <<<
7 特别注意
需要特别、特别、特别注意的是:但凡是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对象,导致鉴权信息丢失,所示每次都要重新设置鉴权信息。
ONVIF协议网络摄像机(IPC)客户端程序开发(9):鉴权(认证)相关推荐
- ONVIF协议网络摄像机(IPC)客户端程序开发使用gSOAP生成ONVIF框架代码(C++)03-->Windows
其它的不多说,直接开始步骤. 我的版本是2.8.109,目前最新版本. 实际上,onvif的源码是兼容Linux.Windows版本的,例如如果你已经在这篇文章ONVIF协议网络摄像机(IPC)客户端 ...
- ONVIF协议网络摄像机(IPC)客户端程序开发(3):理解什么是Web Services
ONVIF协议网络摄像机(IPC)客户端程序开发(3):理解什么是Web Services 1. 专栏导读 本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解,专栏前面文 ...
- ONVIF协议网络摄像机(IPC)客户端程序开发(2):第一次使用IPC摄像头
ONVIF协议网络摄像机(IPC)客户端程序开发(2):第一次使用IPC摄像头 1. 专栏导读 2. 适合读者 本文只适合第一次拿到IPC摄像头,很好奇该怎么使用IPC的读者.已经玩过IPC的,可以略 ...
- ONVIF协议网络摄像机(IPC)客户端程序开发(8):获取设备基本信息
ONVIF协议网络摄像机(IPC)客户端程序开发(8):获取设备基本信息 1 专栏导读 本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解,专栏前面文章讲过的知识点(或代 ...
- ONVIF协议网络摄像机(IPC)客户端程序开发(5):门外汉理解ONVIF协议
1. 专栏导读 本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解,专栏前面文章讲过的知识点(或代码段),后面文章不会赘述.为了节省篇幅,突出重点,在文章中展示的示例代码 ...
- 自行实现ONVIF协议网络摄像机(IPC)开发(0):专栏开篇
一. 前言 最近做了一个海思车载视频的项目,设备作为客服端实现对市场上主流IPC视频流的获取,现在网上很多资料基本都是使用Web Services组成API实现的,这里博主所有ONVIF协议都是通过自 ...
- ONVIF网络摄像头(IPC)客户端开发—ONVIF介绍
1.前言: 网上已经有很多关于ONVIF开发的资料,这里概括介绍一下ONVIF协议以及介绍一下我自己在开发ONVIF网络摄像头的一些流程和经验,做个开发记录和经验总结,以备将来查看,也可供他人参考.如 ...
- 如何利用UDP组播实现海康网络摄像机(IPC)的自动探测【源码】【监控】【录播】【NVR】【ONVIF】
前言: 监控项目中,经常会遇到管理大量网络摄像机IPC的情况,如果每个IPC都要手动输入IP和端口,是非常繁琐的事情,于是,出现了与设备无关的ONVIF协议.海康提供的SADPTool就是基于ONVI ...
- 网络编程之TCP客户端程序开发
网络编程之TCP客户端程序开发 1. 开发 TCP 客户端程序开发步骤 2. socket 类的介绍 3. TCP 客户端程序开发示例代码 4. 小结 1. 开发 TCP 客户端程序开发步骤 创建客户 ...
最新文章
- 软件测试培训怎么学?有没有发展前景?
- AI如何设计,才能人类利益最大化?
- roast和roasting区别_《吐槽大会》的英文居然是roast!为什么?
- Ajax ToolKit --- ModelPopupExtender应用经验二则
- XXXXX CodeForces - 1364A(思维)
- 《SpringBoot揭秘 快速构建微服务体系》读后感(三)
- python 二进制流_Python中对字节流/二进制流的操作:struct模块简易使用教程
- 《Java基础学习笔记》JAVA基础
- 数字信号处理实验(六)—— 心电信号处理 IIR FIR滤波综合题(下篇)
- DevExpress Windows Form(1) DevExpress控件之主题
- 发布一款小软件:和讯博客助手-新闻采集测试版- 0.1.0
- 汉印CP4000照片打印机体验
- java有哪些技术领域
- 爬虫之-bilibili视频下载-接口分析
- sqlite3查询表中最后一条记录
- Linux下挂载NTFS分区
- 【模拟器】华为模拟器eNSP安装注意事项及常见报错处理
- 很简单的html+js,程序员的浪漫,可以让你小女朋友点开哈。哈哈哈
- Windows10怎么卸载删除微软拼音输入法
- linux下route路由设置命令详解