lumeohq / onvif-rs

A native Rust ONVIF client library.
MIT License
114 stars 61 forks source link

Reuse digest auth challenge #131

Closed DmitrySamoylov closed 1 month ago

DmitrySamoylov commented 1 month ago

Digest auth works this way:

The problem here is that for multiple requests to the same service (let's say to media service http://192.168.0.128/onvif/Media), we perform an extra request to obtain a new challenge. However, we can reuse the challenge from the very first 401 and receive 200's in following requests immediately. This challenge gets stale at some point, though, so I handled this as well in this PR.

Before:

2024-10-11T11:59:54.728210Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 401 Unauthorized
2024-10-11T11:59:54.763040Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 200 OK
2024-10-11T11:59:54.788537Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 401 Unauthorized
2024-10-11T11:59:54.832126Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 200 OK
2024-10-11T11:59:54.860021Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 401 Unauthorized
2024-10-11T11:59:54.892962Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 200 OK
2024-10-11T11:59:54.919252Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 401 Unauthorized
2024-10-11T11:59:54.953114Z DEBUG onvif::soap::client: http://192.168.0.128/onvif/Media: Response status: 200 OK

After:

2024-10-11T11:42:00.963856Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 401 Unauthorized
2024-10-11T11:42:00.995125Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
2024-10-11T11:42:01.058180Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
2024-10-11T11:42:01.098189Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
2024-10-11T11:42:01.138092Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
2024-10-11T11:42:01.178275Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
... a minute later nonce gets too old, so we get a new challenge and continue working
2024-10-11T11:43:00.994051Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 401 Unauthorized
2024-10-11T11:43:01.027800Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
2024-10-11T11:43:01.068052Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
2024-10-11T11:43:01.108224Z DEBUG request{uri="http://192.168.0.128/onvif/Media"}: onvif::soap::client: Response status: 200 OK
...

For context: we need this for VMSes which tend to have hundreds of cameras connected, and we have to do GetStreamUri in a separate request for each camera. ONVIF doesn't have bulk requests, so per-request optimizations now make some sense.