mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-05 14:47:40 +03:00
feat: add auth_mode option to ONVIF config for Hikvision HTTP Digest support
Some Hikvision PTZ cameras (e.g. DS-2SE4C425MWG-E) reject WSSE wsUsername
tokens and return 401 on /onvif/Media and /onvif/PTZ endpoints. They require
HTTP Digest authentication at the transport level before processing SOAP.
Add `auth_mode` field to OnvifConfig (auto/digest/wsse, default: auto).
When auth_mode=digest, inject aiohttp.DigestAuthMiddleware into the
ONVIFCamera session so Digest challenge-response completes before SOAP.
Usage:
cameras:
my_hikvision_ptz:
onvif:
host: 192.168.31.86
port: 80
user: admin
password: yourpassword
auth_mode: digest
Fixes #22622
This commit is contained in:
parent
4b42039568
commit
27c80b4944
@ -1,5 +1,5 @@
|
||||
from enum import Enum
|
||||
from typing import Optional, Union
|
||||
from typing import Literal, Optional, Union
|
||||
|
||||
from pydantic import Field, field_validator
|
||||
|
||||
@ -117,6 +117,11 @@ class OnvifConfig(FrigateBaseModel):
|
||||
title="Disable TLS verify",
|
||||
description="Skip TLS verification and disable digest auth for ONVIF (unsafe; use in safe networks only).",
|
||||
)
|
||||
auth_mode: Literal["auto", "digest", "wsse"] = Field(
|
||||
default="auto",
|
||||
title="ONVIF authentication mode",
|
||||
description="Authentication mode for ONVIF connections. 'auto' tries WSSE first (default behavior). 'digest' forces HTTP Digest auth at the transport level — required for some Hikvision cameras that reject WSSE wsUsername tokens and return 401. 'wsse' forces WSSE UsernameToken only.",
|
||||
)
|
||||
autotracking: PtzAutotrackConfig = Field(
|
||||
default_factory=PtzAutotrackConfig,
|
||||
title="Autotracking",
|
||||
|
||||
@ -9,6 +9,7 @@ from importlib.util import find_spec
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import aiohttp
|
||||
import numpy
|
||||
from onvif import ONVIFCamera, ONVIFError, ONVIFService
|
||||
from zeep.exceptions import Fault, TransportError
|
||||
@ -104,6 +105,20 @@ class OnvifController:
|
||||
if password is not None and isinstance(password, bytes):
|
||||
password = password.decode("utf-8")
|
||||
|
||||
# Build extra kwargs for digest auth mode (Hikvision and similar cameras
|
||||
# that reject WSSE wsUsername tokens and require HTTP Digest at transport level).
|
||||
onvif_extra: dict[str, Any] = {}
|
||||
if cam.onvif.auth_mode == "digest" and user and password:
|
||||
try:
|
||||
onvif_extra["middlewares"] = [
|
||||
aiohttp.DigestAuthMiddleware(user, password)
|
||||
]
|
||||
except AttributeError:
|
||||
logger.warning(
|
||||
f"DigestAuthMiddleware not available in installed aiohttp version "
|
||||
f"for camera {cam_name}; falling back to default auth."
|
||||
)
|
||||
|
||||
self.cams[cam_name] = {
|
||||
"onvif": ONVIFCamera(
|
||||
cam.onvif.host,
|
||||
@ -113,6 +128,7 @@ class OnvifController:
|
||||
wsdl_dir=str(Path(find_spec("onvif").origin).parent / "wsdl"),
|
||||
adjust_time=cam.onvif.ignore_time_mismatch,
|
||||
encrypt=not cam.onvif.tls_insecure,
|
||||
**onvif_extra,
|
||||
),
|
||||
"init": False,
|
||||
"active": False,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user