gSOAP HTTP Digest Authentication
gSOAP HTTP Digest Authentication
ONVIF 的 gSOAP HTTP摘要认证实现步骤。
添加plugin/httpda.c
, plugin/smdevp.c
, plugin/threads.c
到工程。
按照官网教程将认证代码添加到工程中。(例如添加到GetDeviceInfo接口中)
#include "httpda.c"
struct soap *soap = soap_new();
soap_register_plugin(soap, http_da); //after new_soap() and before soap_bind
...
soap_serve(soap); // see gSOAP documentation and examples on how to serve requests
...
int ns__method(struct soap *soap, ...)
{
if (soap->userid && soap->passwd) // Basic authentication
{
if (!strcmp(soap->userid, userid) && !strcmp(soap->passwd, passwd))
{
... // can also check soap->authrealm
... // process request and produce response
return SOAP_OK;
}
}
else if (soap->authrealm && soap->userid) // Digest authentication
{
passwd = ... // database lookup on userid and authrealm to find passwd
if (!strcmp(soap->authrealm, authrealm) && !strcmp(soap->userid, userid))
{
if (!http_da_verify_post(soap, passwd)) // HTTP POST DA verification
{
... // process request and produce response
return SOAP_OK;
}
}
}
soap->authrealm = authrealm; // realm to send to client
return 401; // Not authorized, challenge with digest authentication
}
这时Server给Client回的HTTP请求头部格式存在问题,Client无法识别,导致给Server回的信息中不带userid和authrealm,因此会导致认证失败。解决方法是修改httpda.c
中Server给Client回HTTP消息时的请求头格式。
在httpda.c
中,修改http_da_post_header(struct soap *soap, const char *key, const char *val)
中soap->tmpbuf中的格式信息,修改如下:
if (data->option > 0)
{
// (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->authrealm) + strlen(nonce) + strlen(opaque) + 59), "Digest algorithm=%s, realm=\"%s\", qop=\"auth,auth-int\", nonce=\"%s\", opaque=\"%s\"", alg, soap->authrealm, nonce, opaque);
(SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->authrealm) + strlen(nonce) strlen(opaque) + 59), "Digest qop=\"auth\", realm=\"%s\", nonce=\"%s\", opaque=\"%s\", stale=\"FALSE\"", soap->authrealm, nonce, opaque);
// if (data->fposthdr(soap, key, soap->tmpbuf))
// return soap->error;
}
//(SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->authrealm) + strlen(nonce) + strlen(opaque) + 59), "Digest algorithm=MD5, realm=\"%s\", qop=\"auth,auth-int\", nonce=\"%s\", opaque=\"%s\"", soap->authrealm, nonce, opaque);
return data->fposthdr(soap, key, soap->tmpbuf);
此时通过ONVIF 测试工具的check
选项(默认HTTP Digest Authentication)进行HTTP Digest鉴权认证,能够调用GetDeviceInfo得到设备信息。此时,和海康威视的摄像头一样,前面会进行两次发送,告知Client需要带上鉴权信息。(这里的check是需要Server进行三次发送。但是按照HTTP Digest的规定是发送两次。 后续的Digest也确实是发送两次,check除外,不清楚原因)
river@river-vm:/mnt/hgfs/onvif_3/build$ ./server 1
INFO: Not find key [ipv6]
INFO: Not find key [ipv6]
onvif_start_httpserver
[http_da_init] ....
SIOCADDRT: 不允许的操作
onvif_start_discovery
ip:192.168.1.100
__tds__GetUsers
http soap_serve
__tds__GetDeviceInformation
opaque: c7cd8887
Starting session realm=IPC_CAM nonce=5f23d1ffca530cc0538a
SOAP 1.2 fault SOAP-ENV:Sender [no subcode]
"Error 401: HTTP 401 Unauthorized"
Detail: [no detail]
__tds__GetDeviceInformation
opaque: 4b07732e
Starting session realm=IPC_CAM nonce=5f23d1ffca54e1db7e37
SOAP 1.2 fault SOAP-ENV:Sender [no subcode]
"Error 401: HTTP 401 Unauthorized"
Detail: [no detail]
__tds__GetDeviceInformation
INFO userid: user5
INFO authrealm: IPC_CAM
INFO Digest id and passwd not null
Debug message: updating session realm=IPC_CAM nonce=5f23d1ffca54e1db7e37
INFO Digest
http soap_serve
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!