gSOAP HTTP Digest Authentication

gSOAP HTTP Digest Authentication

ONVIF 的 gSOAP HTTP摘要认证实现步骤。

gSOAP官网教程

添加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回的信息中不带useridauthrealm,因此会导致认证失败。解决方法是修改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
posted @   duapple  阅读(112)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!
点击右上角即可分享
微信分享提示