? ? ? ? 前段时间突然遇到有一个需求:要求能够抓取到NVR上连接的摄像头设备列表。

? ? ? ? 因为要的比较急,而且我还没啃透海康SDK的文档,所以只好考虑另辟蹊径,用一些别的方法来达到目标咯。

? ? ? ? 我们登录到NVR的web控制页面不难发现,左侧可不就是我想要的设备列表吗!?

那么,问题来了,我要怎么搞到这一块的数据呢?

? ? ? ? 打开F12开发者工具,我们可以观察到浏览器发送了哪些请求,并接收到了哪些服务器响应的数据,经过筛查,我发现了有一个浏览器发起的请求,请求到的结果似乎就是我想要的东西。

? ? ? ? 我们把这个请求的URL复制出来,单独观察看看:

http://192.168.0.109/ISAPI/ContentMgmt/InputProxy/channels?security=1&iv=decb6a649cd7e051546206bdd6159c98

? ? ? ? 通过观察这个URL地址,可以发现这里请求的NVR的ip是:192.168.0.109,NVR开放的端口是:80,

请求的资源是:/ISAPI/ContentMgmt/InputProxy/channels

请求时还带了几个参数:security和iv。至于这两个参数是啥意思,我还不知道。

? ? ? ? 但是本着“删繁就简”的原则,我可以去测试一下这些参数。

? ? ? ? 首先把URL粘贴进浏览器中,我们手动发起访问,看看是个什么结果:

访问结果是网页弹出了一个简易的认证页面,要求你输入账号和密码才能登录。

? ? ? ? 在我们输入了正确的账号和密码之后,这个地址显示出了一份包含了所有设备的xml:

当我输入错误的账号密码或者点击“取消”时,则会返回一份提示401错误的xml:

? ? ? ? 经过几轮测试,我发现前面说到的请求带的两个参数:security和iv,即使删掉也能够正常地获取到xml。那么我需要请求的URL地址就简化成了:

http://192.168.0.109/ISAPI/ContentMgmt/InputProxy/channels
? ? ? ? 到目前为止,我遇到的问题就简化成了:如何抓取到上面这个URL下的xml,并且解析出设备列表。解决这个问题的小目标也明确了:

1、模拟登陆这个网页,然后获取到xml;

2、解析xml,拿到所需要的设备信息。

? ? ? ? 首先咱先可以完成第一个小目标,模拟登陆这个网页。

? ? ? ? 电视机前有心的小朋友肯定注意到了,上面截图中,弹出的这个认证页面和一般账号密码form是很不一样的,它比较简陋,而且是浏览器主动弹出来的,不是显示在页面上的。这其中究竟发生了什么呢?

? ? ? ? 我们可以抓个包来看看。(因为chrome的开发者工具抓到的包比较简陋,分析不出啥有用的信息,所以我就用Fiddler抓包了。)

? ? ? ? 再使用浏览器完成了一次请求之后,我们轻而易举地在Fiddler里面发现抓到了两个包:

? ? ? ? 第一个响应码为401的数据包里面的报文信息是这样的:

? ? ? ? 上图中蓝色的部分为服务器返回的,提示需要认证的信息(因为http 401代码表示你未授权,因此需要验证你的身份信息),这里我们可以发现服务器提供了两种认证算法方式:基本(Basic)认证和摘要(Digest)认证。

? ? ? ? 然后再看我们在输入正确的账号和密码之后,浏览器发出的数据包(就是下面那个状态码是200的):

![]http://wishes-blog.cn/upload/2019/0/TIM截图201901151509522019011515504951.png)

不难发现,数据包中包含了一项很特别的参数:Authorization。浏览器发送的这个数据完整的是这样的:

Digest username="admin", realm="DVRNVRDVS", nonce="b0a97d26d1216728a76f9cc23fdc1917:1547564458637", uri="/ISAPI/ContentMgmt/InputProxy/channels", algorithm=MD5, response="45924b8342669b4493532a8352b628d0", qop=auth, nc=00000001, cnonce="2095e2d3b12ae7ce"

? ? ? ? 这里需要先补充一下HTTP 401认证的一些基本知识,特别是其中摘要(Digest)算法的知识:认证模式之Digest模式?

以及?digest 用户认证 response生成算法

? ? ? ? 这些都了解了之后。那么剩下的问题也就不难了:我们按照标准的digest算法,计算出正确的数据,并且把它发送给服务器,那不就认证通过啦?

? ? ? ? 这里我用Java写了一个能计算出正确Response值且能完成自动登录并拿到xml的demo。代码这里不多赘述,这里仅说明一下关键的步骤和原理:

严格按照Digest算法的计算步骤算各项MD5值,且每一项都要取小写字符(大写字符算出来的MD5值不一样),那么最后算出来的Response值便是正确的MD5值。

? ? ? ? 然后我们重写toString()方法,把计算出来的结果,格式化为标准的Digest header格式:

? ? ? ? 最后我们将计算出来的结果放在http请求的header中,发送给服务器,应该就能验证通过了。

? ? ? ? 测试一下,能拿到数据。

? ?

? ? ? ? 至于最后的解析我用的是dom4j。这个不复杂,在这里就不多赘述了。

? ? ? ? 最后附上这个小demo:模拟Digest认证的登录demo


摸鱼癌晚期患者