ESP32 Arduino http协议digest认证 接入海康威视摄像机

2023-05-16

注意:使用的是ArduinoHttpClient,与ESP32内部的HTTPClient库有较大的差别

  1. 海康摄像机http接入时候,由于没有认证信息,会返回401无权限信息,这时需要进行digest认证;
  2. 首次请求后返回digest认证信息,使用字符处理提取出qop、realm、nonce这几个关键字
  3. 然后就需要进行digest加密了,这个时候可以参考如下几篇博文确认加密原理
    1. http Digest认证计算方法整理_TYINY的博客-CSDN博客_digest 算法
    2. http://web.chacuo.net/safedigestauth
    3. md5加密,sha1加密--md5在线解密
  4. 通过ESP内部的MD5库进行加密,将认证信息放入到header中再次请求,即可实现摄像机的连接
#include <Arduino.h>
#include <HttpClient.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include "MD5Builder.h"



char ssid[] = "xxxxx";    //按需调整
char pass[] = "xxxxx";    //按需调整

WiFiClient wifi;
HttpClient client = HttpClient(wifi, "10.17.97.117", 80);  //IP为摄像机的IP,80为http的端口

void setup() {

    Serial.begin(115200);
    Serial.println();
    Serial.println();
    Serial.println();

    //wifi连接
    WiFi.begin(ssid, pass);
    while ( WiFi.status()  != WL_CONNECTED) {
      Serial.print("Attempting to connect to Network named: ");
      Serial.println(ssid);   // print the network name (SSID);
      // Connect to WPA/WPA2 network:
      sleep(2);
    }
    
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}

void loop() {
    String devAuthStr;
    String retAuthStr;
    String response;
    String qop;
    String realm;
    String nonce;
    String nc="00000001";
    String cnonce = "f66f3849aa2540cb";
    String stra1,stra2;
    String strUri = "/ISAPI/System/deviceInfo";

    
    Serial.print("[HTTP] begin...\n");

    client.get("/ISAPI/System/deviceInfo");

    // read the status code and body of the response
    int statusCode = client.responseStatusCode();
    Serial.printf("[HTTP] GET... code: %d\n", statusCode);

    // httpCode will be negative on error
    if(statusCode == 200) 
    {
        String response = client.responseBody();
        Serial.print("Response: ");
        Serial.println(response);
    } 
    else if(401 == statusCode) //需要进行digest认证
    {
        // from header get auth info
        while(client.headerAvailable())
        {
          
          if(0 == client.readHeaderName().compareTo("WWW-Authenticate"))
          {
            devAuthStr = client.readHeaderValue();
            break;
          }
        }
        Serial.println(devAuthStr);
        int index1=0;
        int index2=0;
        index1 = devAuthStr.indexOf("qop");
        index2 = devAuthStr.indexOf(",", index1);
        qop = devAuthStr.substring(index1+5, index2-1);
        index1 = devAuthStr.indexOf("realm");
        index2 = devAuthStr.indexOf(",", index1);
        realm = devAuthStr.substring(index1+7, index2-1);
        index1 = devAuthStr.indexOf("nonce");
        index2 = devAuthStr.indexOf(",", index1);
        nonce = devAuthStr.substring(index1+7, index2-1);
        Serial.println(qop);
        Serial.println(realm);
        Serial.println(nonce);
        MD5Builder md5;
        
        md5.begin();
        md5.add("admin:");
        md5.add(realm);
        md5.add(":abcd1234");
        md5.calculate();
        stra1 = md5.toString();
        
        md5.begin();
        md5.add("GET:");
        md5.add(strUri);
        md5.calculate();
        stra2 = md5.toString();

        md5.begin();
        md5.add(stra1);
        md5.add(":");
        md5.add(nonce);
        md5.add(":");
        md5.add(nc);
        md5.add(":");
        md5.add(cnonce);
        md5.add(":");
        md5.add(qop);
        md5.add(":");
        md5.add(stra2);
        md5.calculate();
        response = md5.toString();

        retAuthStr = "Authorization: Digest username=\"admin\", realm=\""+realm+"\", nonce=\""+nonce+"\", uri=\""+strUri+"\", response=\""+response+"\", qop=\""+qop+"\", nc="+nc+", cnonce=\""+cnonce+"\"";  
        Serial.println(retAuthStr);  
        
        client.beginRequest();
        client.get(strUri);
        client.sendHeader(retAuthStr);
        client.endRequest();

        statusCode = client.responseStatusCode();
        Serial.printf("[HTTP] GET... code: %d\n", statusCode);
        String responseRes = client.responseBody();
        Serial.print(responseRes);

    }
    else
    {
        Serial.printf("[ERROR][HTTP] GET... code: %d, can not process!\n", statusCode);      
    }

    Serial.println();
    Serial.println();
    Serial.println();

    delay(60000);
}

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

ESP32 Arduino http协议digest认证 接入海康威视摄像机 的相关文章

  • 如何将 html 输入到 Flask 中?

    我有这个 html 位
  • 在获得响应之前发出多个请求

    当并行发送多个请求时 在获得响应之前 我无法理解 HTTP 的工作原理 有两种情况 1 With Connection Keep Alive 根据HTTP规范 http www w3 org Protocols rfc2616 rfc261
  • 我应该使用哪种协议来传输音频(非直播)? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 处理原始 HTTP 请求内容

    我正在 ASP NET 中做一个电子商务解决方案 它使用PayPal 网站支付标准 https www paypal com IntegrationCenter ic standard home html服务 除此之外 我还使用他们提供的服
  • 在链接时合并全局数组/从多个编译单元填充全局数组

    我想定义一系列的东西 比如事件处理程序 的内容 该数组在编译时是完全已知的 但定义在 多个编译单元 分布在多个库中 至少在最终 静态 链接之前是相当解耦的 我想要 也保持这种方式 因此添加或删除编译单元将 还可以自动管理事件处理程序 而无需
  • Python串口通信

    我正在开发一个 Arduino 项目 由于内存限制 我将其与 Python 脚本连接起来 在Python方面 我有一个二维矩阵 其中包含各自的x y坐标值 并且在此列表中有26000个坐标对 因此 为了向大家澄清数据结构 pathlist
  • Node.js 中的 HTTPS 代理服务器

    我正在开发一个node js代理服务器应用程序 我希望它支持HTTP and HTTPS SSL 协议 作为服务器 我目前正在使用node http proxy https github com nodejitsu node http pr
  • 如何从 Kubernetes 服务背后的 HTTP 请求读取客户端 IP 地址?

    我的 Web 应用程序作为 Kubernetes pod 在 SSL 的 nginx 反向代理后面运行 代理和我的应用程序都使用 Kubernetes 服务进行负载平衡 如所述here http blog kubernetes io 201
  • gRPC(HTTP/2) 比使用 HTTP/2 的 REST 更快吗?

    目标是引入一种性能更好的传输和应用层协议latency and 网络吞吐量 目前 该应用程序使用REST with HTTP 1 1并且我们遇到了很高的延迟 我需要解决这个延迟问题并且我愿意使用gRPC HTTP 2 or 休息 HTTP2
  • 从开放的 HTTP 流中读取数据

    我正在尝试使用 NET WebRequest WebResponse 类来访问 Twitter 流 API 此处 http stream twitter com spritzer json 我需要能够打开连接并从打开的连接中增量读取数据 目
  • 反向代理受 NTLM 保护的网站

    如何将请求代理到受 NTLM 保护的网站 例如团队基金会 and 共享点 我不断得到401 身份验证错误 根据这篇 Microsoft TechNet 文章 https www microsoft com technet prodtechn
  • 有人成功用 Robolectric 模拟 HttpRequests 吗?

    我刚刚开始使用 Robolectric 模拟大多数 Android 类似乎工作正常 但是当我的测试类尝试创建 DefaultHttpClient 时 它会收到可怕的 Stub 错误 被测试的类在这一行失败 HttpClient httpcl
  • 删除 servlet 中的 cookie 时出现问题

    我尝试使用以下代码删除 servlet 中的 cookie Cookie minIdCookie null for Cookie c req getCookies if c getName equals iPlanetDirectoryPr
  • Vertx HttpClient getNow 不工作

    我的 vertx HttpClient 有问题 下面的代码显示使用 vertx 和纯 java 测试 GET Vertx vertx Vertx vertx HttpClientOptions options new HttpClientO
  • 如何测试“If-Modified-Since”HTTP 标头支持

    使用 PHP 如何准确测试远程网站supports If Modified Since HTTP 标头 据我所知 如果您获取的远程文件自标头请求中指定的日期以来已被修改 它应该返回 200 OK 状态 如果尚未修改 则应返回 304 Not
  • POST 后使用 303 重定向以避免“网页已过期”:如果字节数超过 GET 请求可以处理的字节数,它会工作吗?

    我想解决 网页已过期 问题 首先 我刚刚将 POST 更改为 GET 但这导致出现错误 我的 HTTP 请求超出了 GET 的最大大小 所以 现在我想尝试下面链接中描述的技术 帖子 303 重定向 但是我仍然会遇到相同的大小限制问题吗 对
  • 为什么使用HTTP协议时需要指定端口号?

    即使我们使用HTTP协议 为什么还需要用IP地址指定端口号 例如 http xyz 8080 这到底是什么意思 我们已经知道 在使用 HTTP 时 请求将在端口 80 上提供服务 那么为什么我们要显式指定端口呢 HTTP 的默认端口为 80
  • 使用 Arduino 来操作 Android [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有人尝试过让 Android 和 Arduino 相互通信吗 我在网上找到了几个项目 Amarino http www amarino tool
  • 如何确定服务器是否支持 Range 标头?

    我一直在尝试使用 Range 标头值从特定点流式传输音频 但我总是从一开始就得到歌曲 我正在通过程序执行此操作 因此不确定问题是否出在我的代码中或服务器上 如何确定服务器是否支持 Range 标头参数 Thanks 方式HTTP规范 htt
  • 如何使用批处理脚本调用的curl 获取http post 请求的响应代码?

    我正在努力为从我们的工具之一发送 http post 请求提供支持 该工具基本上通过 http 请求执行作业 实现此目的的方法是该工具使用多个参数调用 RunScript bat 该脚本解析这些参数并在验证后发出curl post 请求 P

随机推荐