Как безопасно воспроизводить потоковый файл .m3u8 с AWS S3 с помощью CloudFront?

Я использую подписанный URL-адрес CloudFront для отображения изображений и видео с S3, которые необходимо защитить.

Он хорошо работает с изображениями и другими видео, за исключением файла .m3u8.

Я использовал AWS PHP SDK, и вот мой код.

<?php
    // Instantiate the CloudFront client with your AWS credentials
    $cloudFrontClient    =  new CloudFrontClient(array(
        'region'        => env('AWS_DEFAULT_REGION'),
        'version'       => 'latest',
        'http'          => [ 'verify' => false ],
        'credentials'   => array(
            'key'       => env('AWS_ACCESS_KEY_ID'),
            'secret'    => env('AWS_SECRET_ACCESS_KEY'),
    )));
    
    // Create a signed URL for the resource
    $resourceKey      =  'https://abcdefg.cloudfront.net/test/file_1000k.m3u8';
        $expires          =  time() + 3600;
        $signedUrl        =  $cloudFrontClient->getSignedUrl([
            'url'         => $resourceKey,
            'expires'     => $expires,
            'private_key' => public_path().'/pk-ABCD123.pem',
            'key_pair_id' => 'ABCD123ABCD123ABCD123'
        ]);
?>
    <video id='hls-example' class="video-js vjs-default-skin" width="640" height="480" controls>
        <source src="<?php echo $signedUrl; ?>" type="application/x-mpegURL">
        Your browser does not support the video tag.
    </video>
    
    <script src="https://vjs.zencdn.net/7.2.3/video.js"></script>
    <script src="<?php echo asset('public/assets/js/videojs-contrib-hls.min.js'); ?>"></script>
    <script>
        var player = videojs('hls-example');
        player.play();
    </script>

Если я не ошибаюсь, он не воспроизводится, потому что нам также нужно подписать сегментированные файлы (.ts) внутри файла .m3u8.

Как мы можем динамически изменить его?

Есть ли способ безопасно воспроизвести файл .m3u8, чтобы пользователи не могли использовать прямой доступ по ссылке для загрузки файла?


person JSN    schedule 28.05.2020    source источник


Ответы (2)


Подписанные URL-адреса CloudFront прекрасно работают, когда это всего лишь один файл, но, как вы уже поняли, это проблема, когда у вас есть несколько ресурсов.

По этой причине рекомендуется использовать signed Файлы cookie CloudFront.

При этом вам нужно подписать только один раз, чтобы разрешить все ресурсы из определенного дистрибутива CloudFront, и вам не нужно беспокоиться о процессе подписания при каждой загрузке страницы.

person Chris Williams    schedule 04.06.2020
comment
Ааа, у вас есть идея, как это реализовать? - person JSN; 05.06.2020
comment
Это аналогичный процесс для подписанных URL-адресов, вы используете CLI или SDK. На этой странице содержится дополнительная информация о деталях реализации:docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ - person Chris Williams; 05.06.2020

Это хорошая статья AWS, которая поможет вам выбрать между (1) файлами cookie и (2) подписанными URL-адресами: -

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-choosing-signed-urls-cookies.html

Сначала я рассматривал подход с использованием файлов cookie, но выбрал индивидуальную подпись каждого URL-адреса в файле манифеста HLS. Я использую ffmpeg для преобразования файла MP4 в HLS (например, Mp4 в HLS с использованием ffmpeg) и манифест HLS будет выглядеть примерно так: -

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:17
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:16.683333,
my-video0.ts
#EXTINF:8.341667,
my-video1.ts
#EXTINF:8.341667,
my-video2.ts

...

#EXT-X-ENDLIST

Вы бы индивидуально подписали каждый сегмент, например.

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:17
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:16.683333,
https://cqtgd3b9n5c6qp.cloudfront.net/my-video0.ts?Expires=1609499278&Key-Pair-Id=AIRPEGWQPKAIQ7O3SPLI&Signature=KUvRsV-OpJ014ZQ0dLZF....
#EXTINF:8.341667,
https://cqtgd3b9n5c6qp.cloudfront.net/my-video1.ts?Expires=1609499278&Key-Pair-Id=AIRPEGWQPKAIQ7O3SPLI&Signature=KlVQsz5TVzhEQ8LKs1ZW....
#EXTINF:8.341667,
https://cqtgd3b9n5c6qp.cloudfront.net/my-video2.ts?Expires=1609499278&Key-Pair-Id=AIRPEGWQPKAIQ7O3SPLI&Signature=VR1MBzq~pVsBfOzjZa~M....

...

#EXT-X-ENDLIST

Простой поиск/замена будет динамически генерировать этот файл.

Подписание каждого URL требует некоторой обработки, поэтому я добавляю заголовок Expires (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires) в ответ HTTP при возврате манифеста HLS. Это гарантирует, что последующие вызовы в браузере будут использовать кэшированную копию, что значительно повысит производительность.

ПРИМЕЧАНИЕ. Важно, чтобы срок действия в ответе HTTP был (немного) меньше, чем срок действия в подписанном URL-адресе.

Я считаю, что индивидуальная подпись каждого URL-адреса более безопасна, и вам не нужно беспокоиться о доменах и т. Д., Но, вероятно, это немного сложнее (с точки зрения кода) для реализации.

person bobmarksie    schedule 30.12.2020