当在 php 代码中发出请求时,在 URL 中使用用户名和密码的 http 请求失败,但在任何浏览器中都有效
http request with user and password in URL fails when request is made in php code, but works in any browser
在我的 PC 浏览器中访问此 URL 时,我看到了我的 HikVision NVR 录制的流的屏幕截图
http://admin:441e3!@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080
但是当我尝试从 Apache 服务器在同一网络中的 RaspberryPi 板上执行的 php 文件访问相同的 url 时,出现 401 Unauthorized 错误,我尝试了 3访问 url 和 none 的不同方式有效
<?php
/* v1 */
$data = file_get_contents("http://admin:441e3!@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080");
header('Content-type: image/jpeg');
echo $data;
/* v2 */
$username = 'admin';
$password = '441e3!';
$url = 'http://192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080';
$context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode("$username:$password")
)
));
$data = file_get_contents($url, false, $context);
header('Content-type: image/jpeg');
echo $data;
/* v3 */
$login = 'admin';
$password = '441e3!';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$login:$password");
$data = curl_exec($ch);
curl_close($ch);
header('Content-type: image/jpeg');
echo $data;
?>
错误是:
v1:
[Tue Nov 02 21:31:17.529527 2021] [:error] [pid 30366] [client 192.168.1.29:65434] PHP Warning: file_get_contents(http://...@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080): failed to open stream: HTTP request failed! HTTP/1.0 401 Unauthorized\r\n in /var/www/html/security _cam3.php on line 30
v2 & v3 error:
[Tue Nov 02 21:55:07.643803 2021] [:error] [pid 26933] [client 192.168.1.29:60984] PHP Warning: file_get_contents(http://192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080) : failed to open stream: HTTP request failed! HTTP/1.0 401 Unauthorized\r\n in /var/www/html/security_cam3.php on line 24
用正确的密码在浏览器中访问URL时,图像正确显示,headers如下:
GENERAL
Request URL: http://admin:441e3!@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080
Request Method: GET
Status Code: 200 OK
Remote Address: 192.168.1.90:80
Referrer Policy: strict-origin-when-cross-origin
RESPONSE HEADERS
HTTP/1.1 200 OK
Connection: close
Pragma: no-cache
Cache-Control: no-cache
Content-Type: image/jpeg
Content-Length: 123814
REQUEST HEADERS
GET /ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080 HTTP/1.1
Host: 192.168.1.90
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
QUERY STRING PARAMETERS
videoResolutionWidth: 1920
videoResolutionHeight: 1080
我也试过直接从 RaspberryPi 命令行访问图像,使用 wget 命令,图像保存正确,所以它一定是 PHP 那边的东西。
root@bananapi:~# wget 'http://admin:441e3!-@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080'
--2021-11-02 22:57:50-- http://admin:*password*@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080
Connecting to 192.168.1.90:80... connected.
HTTP request sent, awaiting response... 401 Unauthorized
Authentication selected: Digest realm="da9ea0f8f352408658c64b0a", domain="::", qop="auth", nonce="e1f5166b2054a18a2a17595a4bbfaf23:1635894137125", opaque="", algorithm="MD5", stale="FALSE"
Reusing existing connection to 192.168.1.90:80.
HTTP request sent, awaiting response... 200 OK
Length: 125170 (122K) [image/jpeg]
Saving to: ‘picture?videoResolutionWidth=1920&videoResolutionHeight=1080’
picture?videoResolutionWidth=1920&videoResolutionHeight=10 100%[======================================================================================================================================>] 122.24K --.-KB/s in 0.003s
2021-11-02 22:57:50 (39.7 MB/s) - ‘picture?videoResolutionWidth=1920&videoResolutionHeight=1080’ saved [125170/125170]
感谢任何帮助。
将我的评论更改为答案:
您真的单独尝试过 v3 而不是组合脚本的一部分吗?如果您使用的是 cURL,您肯定 not 会收到 file_get_contents
错误,这让我怀疑 cURL 可能实际上正在工作(但可能不会返回您期望的数据) .添加检查以查看 cURL 是否为 $data === false
,如果是,则检查 curl_error($ch)
.
的输出
我注意到的另一件事是,根据 wget
代码,看起来使用 HTTP 摘要身份验证 (CURLAUTH_DIGEST
) 而不是基本身份验证成功。
所以,总的来说,我建议下一步这样做:
$login = 'admin';
$password = '441e3!';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, "$login:$password");
$data = curl_exec($ch);
if ($data === false) {
echo 'ERROR: ' . curl_error($ch);
}
else {
header('Content-type: image/jpeg');
echo $data;
}
curl_close($ch);
在我的 PC 浏览器中访问此 URL 时,我看到了我的 HikVision NVR 录制的流的屏幕截图
http://admin:441e3!@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080
但是当我尝试从 Apache 服务器在同一网络中的 RaspberryPi 板上执行的 php 文件访问相同的 url 时,出现 401 Unauthorized 错误,我尝试了 3访问 url 和 none 的不同方式有效
<?php
/* v1 */
$data = file_get_contents("http://admin:441e3!@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080");
header('Content-type: image/jpeg');
echo $data;
/* v2 */
$username = 'admin';
$password = '441e3!';
$url = 'http://192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080';
$context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode("$username:$password")
)
));
$data = file_get_contents($url, false, $context);
header('Content-type: image/jpeg');
echo $data;
/* v3 */
$login = 'admin';
$password = '441e3!';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$login:$password");
$data = curl_exec($ch);
curl_close($ch);
header('Content-type: image/jpeg');
echo $data;
?>
错误是:
v1:
[Tue Nov 02 21:31:17.529527 2021] [:error] [pid 30366] [client 192.168.1.29:65434] PHP Warning: file_get_contents(http://...@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080): failed to open stream: HTTP request failed! HTTP/1.0 401 Unauthorized\r\n in /var/www/html/security _cam3.php on line 30
v2 & v3 error:
[Tue Nov 02 21:55:07.643803 2021] [:error] [pid 26933] [client 192.168.1.29:60984] PHP Warning: file_get_contents(http://192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080) : failed to open stream: HTTP request failed! HTTP/1.0 401 Unauthorized\r\n in /var/www/html/security_cam3.php on line 24
用正确的密码在浏览器中访问URL时,图像正确显示,headers如下:
GENERAL
Request URL: http://admin:441e3!@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080
Request Method: GET
Status Code: 200 OK
Remote Address: 192.168.1.90:80
Referrer Policy: strict-origin-when-cross-origin
RESPONSE HEADERS
HTTP/1.1 200 OK
Connection: close
Pragma: no-cache
Cache-Control: no-cache
Content-Type: image/jpeg
Content-Length: 123814
REQUEST HEADERS
GET /ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080 HTTP/1.1
Host: 192.168.1.90
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
QUERY STRING PARAMETERS
videoResolutionWidth: 1920
videoResolutionHeight: 1080
我也试过直接从 RaspberryPi 命令行访问图像,使用 wget 命令,图像保存正确,所以它一定是 PHP 那边的东西。
root@bananapi:~# wget 'http://admin:441e3!-@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080'
--2021-11-02 22:57:50-- http://admin:*password*@192.168.1.90/ISAPI/Streaming/channels/201/picture?videoResolutionWidth=1920&videoResolutionHeight=1080
Connecting to 192.168.1.90:80... connected.
HTTP request sent, awaiting response... 401 Unauthorized
Authentication selected: Digest realm="da9ea0f8f352408658c64b0a", domain="::", qop="auth", nonce="e1f5166b2054a18a2a17595a4bbfaf23:1635894137125", opaque="", algorithm="MD5", stale="FALSE"
Reusing existing connection to 192.168.1.90:80.
HTTP request sent, awaiting response... 200 OK
Length: 125170 (122K) [image/jpeg]
Saving to: ‘picture?videoResolutionWidth=1920&videoResolutionHeight=1080’
picture?videoResolutionWidth=1920&videoResolutionHeight=10 100%[======================================================================================================================================>] 122.24K --.-KB/s in 0.003s
2021-11-02 22:57:50 (39.7 MB/s) - ‘picture?videoResolutionWidth=1920&videoResolutionHeight=1080’ saved [125170/125170]
感谢任何帮助。
将我的评论更改为答案:
您真的单独尝试过 v3 而不是组合脚本的一部分吗?如果您使用的是 cURL,您肯定 not 会收到 file_get_contents
错误,这让我怀疑 cURL 可能实际上正在工作(但可能不会返回您期望的数据) .添加检查以查看 cURL 是否为 $data === false
,如果是,则检查 curl_error($ch)
.
我注意到的另一件事是,根据 wget
代码,看起来使用 HTTP 摘要身份验证 (CURLAUTH_DIGEST
) 而不是基本身份验证成功。
所以,总的来说,我建议下一步这样做:
$login = 'admin';
$password = '441e3!';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, "$login:$password");
$data = curl_exec($ch);
if ($data === false) {
echo 'ERROR: ' . curl_error($ch);
}
else {
header('Content-type: image/jpeg');
echo $data;
}
curl_close($ch);