PHP请求海康NVR带认证图片URL返回401,浏览器/wget可正常访问
海康威视NVR PHP请求401错误解决方案
原因定位
海康威视ISAPI接口对HTTP认证请求的格式要求较严格,同时Apache运行的PHP环境可能存在授权头被拦截、参数转义异常的问题,常规的Basic Auth写法无法匹配设备的校验规则。
可直接复用的修复方案
方案1:cURL适配写法(优先级最高,兼容性最好)
需要严格按照海康设备要求配置cURL参数,不要提前拼接Authorization头,让cURL自动响应设备的401质询:
<?php $url = 'http://192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080'; $username = 'admin'; $password = '441e3!'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 关键配置:指定用Basic认证,且允许cURL响应401质询 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); // 忽略SSL证书校验,http请求无影响 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 允许跟随设备返回的302跳转 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 禁止自动发送Expect头,海康设备部分版本不兼容该头 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); $output = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if($httpCode == 200) { // 输出或保存图片 header('Content-Type: image/jpeg'); echo $output; } else { echo "请求失败,状态码:".$httpCode; } ?>
方案2:修复file_get_contents上下文写法
如果要使用file_get_contents,需要手动构造严格符合格式的Authorization头,同时确保Apache没有拦截授权头:
- 先在Apache站点配置或.htaccess中添加规则,放行Authorization头:
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
- PHP代码写法:
<?php $url = 'http://192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080'; $username = 'admin'; $password = '441e3!'; $auth = base64_encode("$username:$password"); $context = stream_context_create([ 'http' => [ 'method' => 'GET', 'header' => [ 'Authorization: Basic ' . $auth, 'Expect:' ], // 跟随重定向时保留认证头 'follow_location' => 1, 'max_redirects' => 3 ] ]); $output = file_get_contents($url, false, $context); if($output !== false) { header('Content-Type: image/jpeg'); echo $output; } ?>
额外验证步骤
如果上述方案仍失效,可对比请求头差异定位问题:
- 执行wget时添加
-d参数打印完整请求头:wget -d "http://admin:441e3!@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080" - 在PHP的cURL参数中添加
curl_setopt($ch, CURLOPT_VERBOSE, true);打印请求细节,核对Authorization头、请求方法、其他头是否和wget一致
注意:不要把用户名密码直接拼接在URL中传递给PHP的请求方法,PHP高版本会对URL中的特殊字符做转义,反而会导致认证失败。
内容的提问来源于stack exchange,提问作者ovisopa
相关产品推荐
相关产品推荐

