海康摄像头http抓图

mac2024-04-20  4

老版本的摄像头使用海康的协议http://user:password@192.168.1.64/ISAPI/Streaming/channels/33/picture 就可以取得图片。 然后新型号的摄像头http需要Digest authorization认证。没有认证的话只会返回401unauthorized错误:

<!DOCTYPE html> <html> <head> <title>Document Error: Unauthorized</title> </head> <body> <h2>Access Error: 401 -- Unauthorized</h2> <p>Authentication Error</p> </body> </html>

curl 命令行解决401 unauthorized问题

在https://blog.csdn.net/bobchill/article/details/83302177 里博主用curl 命令行解决401 unauthorized问题,没想到真的可以用。我对应我的应用修改了命令:

curl --insecure --anyauth -u admin:password -X GET http://admin:password@192.168.1.64/ISAPI/Streaming/channels/33/picture >b.jpeg

将接收结果直接输出成b.jpeg文件,确实是一张图片。 但是在openwrt中作用该命令却仍然返回401错误。也许是两个curl版本不同吧。因为最终我还是要通过libcurl编程来实现auth认证的,所以就不深究命令了。

HTTP Digest authentication的机制

是server收到client的HTTP request(INVITE),如果server需要客户端摘要认证,就需要生成一个摘要盘问(digest challenge),通过Response给client一个401 Unauthorized状态发送给用户 摘要盘问如 图二 中的WWW-Authenticate header所示:

摘要盘问中的各个参数意义如下:

realm(领域):必须的,在所有的盘问中都必须有。它是目的是鉴别SIP消息中的机密。在实际应用中,它通常设置为server所负责的域名。

nonce (现时):必须的,这是由服务器规定的数据字符串,在服务器每次产生一个摘要盘问时,这个参数都是不一样的(与前面所产生的不会雷同)。nonce 通常是由一些数据通过md5杂凑运算构造的。这样的数据通常包括时间标识和服务器的机密短语。确保每个nonce 都有一个有限的生命期(也就是过了一些时间后会失效,并且以后再也不会使用),而且是独一无二的(即任何其它的服务器都不能产生一个相同的nonce )。

Stale:不必须,一个标志,用来指示客户端先前的请求因其nonce值过期而被拒绝。如果stale是TRUE(大小写敏感),客户端可能希望用新的加密回应重新进行请求,而不用麻烦用户提供新的用户名和口令。服务器端只有在收到的请求nonce值不合法,而该nonce对应的摘要(digest)是合法的情况下(即客户端知道正确的用户名/口令),才能将stale置成TRUE值。如果stale是FALSE或其它非TRUE值,或者其stale域不存在,说明用户名、口令非法,要求输入新的值。

opaque(不透明体):必须的,这是一个不透明的(不让外人知道其意义)数据字符串,在盘问中发送给用户。

algorithm(算法):不必须,这是用来计算杂凑的算法。当前只支持MD5算法。

qop(保护的质量):必须的,这个参数规定服务器支持哪种保护方案。客户端可以从列表中选择一个。值 “auth”表示只进行身份查验, “auth-int”表示进行查验外,还有一些完整性保护。需要看更详细的描述,请参阅RFC2617。

客户端反馈用户身份 client 生成 生成摘要响应(digest response),然后再次通过 http request (INVITE (Withink digest))发给 server。

摘要响应如 图三 中的Authenticate header所示:

摘要响应中的各个参数意义如下:

username: 不用再说明了 realm: 需要和 server 盘问的realm保持一致 nonce:客户端使用这个“现时”来产生摘要响应(digest response),需要和server 盘问中携带的nonce保持一致,这样服务器也会在一个摘要响应中收到“现时”的内容。服务器先要检查了“现时”的有效性后,才会检查摘要响应的其它部分。

因而,nonce 在本质上是一种标识符,确保收到的摘要机密,是从某个特定的摘要盘问产生的。还限制了摘要盘问的生命期,防止未来的重播攻击。

qop:客户端选择的保护方式。

nc (现时计数器):这是一个16进制的数值,即客户端发送出请求的数量(包括当前这个请求),这些请求都使用了当前请求中这个“现时”值。例如,对一个给定的“现时”值,在响应的第一个请求中,客户端将发送“nc=00000001”。这个指示值的目的,是让服务器保持这个计数器的一个副本,以便检测重复的请求。如果这个相同的值看到了两次,则这个请求是重复的。

response:这是由用户代理软件计算出的一个字符串,以证明用户知道口令。比如可以通过 username、password、http method、uri、以及nonce、qop等使用MD5加密生成。

cnonce:这也是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护。

uri:这个参数包含了客户端想要访问的URI。

server 确认用户 确认用户主要由两部分构成: 检查nonce的有效性 检查摘要响应中的其他信息, 比如server可以按照和客户端同样的算法生成一个response值,和client传递的response进行对比。 ———————————————— 以上出自原文链接:https://blog.csdn.net/andrewpj/article/details/45727853

费话不多说,开干吧,如何通过c语言的libcurl实现呢

c语言的libcurl实现HTTP Digest authentication

先写一个HTTP request(INVITE)请求:

int DigestAuthenticate(void) { char *buffer,*pb; buffer=(char*)calloc(1024,sizeof(char)); memset(buffer,0,1024); pb=buffer; CURL *hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET"); curl_easy_setopt(hnd, CURLOPT_URL, "http://192.168.1.64/ISAPI/Streaming/channels/33/picture"); curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, false); //curl_easy_setopt(hnd, CURLOPT_RETURNTRANSFER, 1); curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, false); curl_easy_setopt(hnd, CURLOPT_TIMEOUT, 30); curl_easy_setopt(hnd, CURLOPT_CONNECTTIMEOUT, 30); curl_easy_setopt(hnd, CURLOPT_HEADER, 1); curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, read_data_curl); curl_easy_setopt(hnd, CURLOPT_WRITEDATA, buffer); CURLcode ret = curl_easy_perform(hnd); if(CURLE_OK == ret) { printf("\n%s\n",buffer); } else{ curl_easy_cleanup(hnd); free(pb); printf("ret:%d\n",ret); return -1; } curl_easy_cleanup(hnd); printf("---------------------end----------------------\n"); free(pb); return 1; }

输出结果:

HTTP/1.1 401 Unauthorized Date: Thu, 31 Oct 2019 12:46:06 GMT Server: webserver X-Frame-Options: SAMEORIGIN Content-Length: 178 Content-Type: text/html Connection: close WWW-Authenticate: Digest qop="auth", realm="IP Camera(D6153)", nonce="597a553359574d334e546f794d5752684d44526c5a673d3d", stale="FALSE" <!DOCTYPE html> <html><head><title>Document Error: Unauthorized</title></head> <body><h2>Access Error: 401 -- Unauthorized</h2> <p>Authentication Error</p> </body> </html>

WWW-Authenticate就是我们需要的东西,接着用它来计算出其它参数。

//这里实现Digest Auth逻辑 String A1 = null; //A1 = MD5("usarname:realm:password"); String A2 = null; //A2 = MD5("httpmethod:uri"); String response = null; //response = MD5("A1:nonce:nc:cnonce:qop:A2");

计算response是个难道。用一个方法可以验证response算得对不对。首先看一下Postman测试中获取的过程,其它的不要,我们看Authorization: Digest 后的字符串,就是这次auth的各个参数:

在https://www.cnblogs.com/johnw/p/5487447.html介绍使用lLinux下使用openss的MD5加密BASE64加密方法。好东西呀,这一下不需要等编程就可以验证计算MD5对不对了。 可以看到结果和上面Postman的response是一样的,证明上面说的Digest Auth逻辑是对的。

最新回复(0)