@accountnujen

Как на сайте отобразить MJPG поток, который требует digest авторизации?

Пытался указать
<img src="http://adminka:admin@192.168.1.8/cgi-bin/mjpg/video.cgi?channel=1&subtype=1" width="720" height="480">

или через <video>, но результат не дало. На камере отключена basic авторизация, доступна только digest...

Если просто открыть ссылку в браузере, то откроется диалоговое окно для ввода логина и пароля и затем откроется картинка-видео.
Какие есть варианты решения?

UPD. Также указываю тег PHP, потому что веду разработку на нём. Может быть есть вариант как-нибудь обмануть сайт, проведя авторизацию?
  • Вопрос задан
  • 85 просмотров
Решения вопроса 1
@accountnujen Автор вопроса
Такс, если кто-то столкнётся с этим, то всё оказалось проще, чем я думал:
Вы создаёте файл, который будет постоянно возвращать то, что отдаёт поток. Загвостка у меня была с заголовком, поэтому ничего не работало. Всё вертится вокруг функции CURLOPT_WRITEFUNCTION => 'streamCallback'.
header('Content-Type: multipart/x-mixed-replace; boundary=myboundary');
function streamCallback($curl, $data) {
    echo $data;
    return strlen($data);
}
$ch = curl_init("$urlcam/cgi-bin/mjpg/video.cgi?channel=1&subtype=1");
curl_setopt_array($ch, [
        CURLOPT_USERPWD => "admin:password",
        CURLOPT_CONNECTTIMEOUT => 20,
        CURLOPT_TIMEOUT => 0,
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_HTTPAUTH=>CURLAUTH_DIGEST,
        CURLOPT_CUSTOMREQUEST => "GET",
        CURLOPT_WRITEFUNCTION => 'streamCallback'
    ]);
$result = curl_exec($ch);
curl_close($ch);

На сайте уже просто указываете ссылку на ваш php файл в картинке:
<img src="https://website/mjpg.php" width="720" height="480">
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Anastasia2306
@Anastasia2306
PHP-разработчик.
Это не будет работать в таком виде, потому что это на уровне браузера стоит защита от таких вот конструкций. Вы правильно указали, что без PHP тут не обойтись. Я бы как-то решила этот вопрос:

<?php
$url = 'http://192.168.1.8/cgi-bin/mjpg/video.cgi?channel=1&subtype=1';

// Функция для digest-авторизации
function digest_parse($txt)
{
    $needed_parts = array('nonce'=>1, 'realm'=>1, 'qop'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@('.$keys.')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}

// Инициализация cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);

// получения заголовков www-Authenticate
$response = curl_exec($ch);

// разбор заголовк а WWW-Authenticate
if (preg_match('/^WWW-Authenticate: Digest (.*)$/im', $response, $matches)) {
    $digest_parts = digest_parse($matches[1]);

    // Создание заголовка Authorization
    // Здесь также надо сгенерить правильный ответ на основе полученных данных и вашего логина и пароля
    // наподобие этого
    $digest_response = ''; // ответ

    // Установка опций для cURL с заголовком Authorization
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Digest username="adminka", realm="'.$digest_parts['realm'].'", nonce="'.$digest_parts['nonce'].'", uri="/cgi-bin/mjpg/video.cgi?channel=1&subtype=1", response="'.$digest_response.'", qop='.$digest_parts['qop'].', nc=00000001, cnonce="d41d8cd98f00b204e9800998ecf8427e"'));
}

// Удаление предыдущих заголовков
curl_setopt($ch, CURLOPT_HEADER, 0);

// Передача потока клиенту
curl_exec($ch);
curl_close($ch);
?>


Ну а потом уже смело в теге img можно сделать так:
<img src="вашскрипт.php" width="720" height="480">

Пример с PHP кодом не полный - я лишь натолкнула вас на мысль, как это может работать. Удачи!
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
YCLIENTS Москва
от 200 000 до 350 000 ₽
Ведисофт Екатеринбург
от 25 000 ₽
ИТЦ Аусферр Магнитогорск
от 100 000 до 160 000 ₽