Практики, используемые в защите видеоконтента электронного обучения
24 мая 2022 г.К сожалению, с увеличением количества данных, которые проходят через Интернет и социальные сети, трудно постоянно отслеживать, был ли ваш контент опубликован без имени или под чьим-то именем (это еще хуже). На самом деле, нарушение авторских прав, плагиат и пиратство — это риски, на которые мы беремся при ведении любого вида бизнеса, особенно при размещении нашей интеллектуальной собственности. онлайн.
В основном с такой ситуацией может столкнуться индустрия онлайн-образования. Лекторы и учебные заведения публикуют свои индивидуальные онлайн-курсы с различными типами контента (видео/аудио/тексты) в программном обеспечении для электронного обучения и предоставляют доступ учащимся. Получая доступ к учебным материалам, учащиеся могут легко копировать-вставлять текст, записывать видео или аудио и свободно делиться ими с другими. Но существует множество средств для обеспечения безопасности контента электронного обучения, которые позволяют владельцам приложений создать безопасную среду, в которой чья-либо интеллектуальная собственность не будет украдена.
Следовательно, когда интеллектуальная собственность и контент распространяются без указания и согласия автора, мы не должны поднимать вокруг этого шумиху. Вместо этого лучше потратить часть своего времени и денег, чтобы убедиться, что вы сделали все для обеспечения безопасности контента электронного обучения. Итак, что вы можете сделать, чтобы предотвратить нарушение авторских прав в вашем программном обеспечении для электронного обучения?
Как защитить онлайн-курсы?
В основном, когда люди мотивированы получить материалы курса и поделиться некоторыми из них, нарушив авторские права, они ищут простые цели. Так что, если ваше ПО для электронного обучения будет иметь хотя бы простую защиту — велика вероятность, что вы отговорите многих из них.
На самом деле ответ на вопрос «Как защитить онлайн-курсы?» зависит от формата контента, который вы хотите защитить. Итак, в этой статье мы собираемся определить основные методы защиты контента электронного обучения. А поскольку большинство программного обеспечения для электронного обучения предлагает видеоматериалы в своих курсах, мы выделим одно из возможных технических решений для обеспечения конфиденциальности вашего видеоконтента.
Но сначала давайте начнем с простого: текст и изображения. Чтобы защитить тексты от плагиата, есть несколько вариантов: от ограничения копирования в буфер обмена и использования специальных сервисов проверки связи до отключения выделения выделения текста с помощью стилей CSS.
Для мультимедийного контента, такого как изображения, ситуация почти такая же, существует множество вариантов применения. Наверное, самый простой способ, который вы немало видели на своем опыте, — использование водяных знаков. Это реализуется с помощью Adobe Photoshop, Digimark, Watermark и других подобных программ. Но, есть еще два варианта, на которые следует обратить внимание: первый - настроить свое изображение таким образом, чтобы при его загрузке пользователь получал пустой файл или файл несуществующего формата, и второй - создание анкор-листа, состоящего из уникального текста фрагменты (ускоряет индексацию контента).
Защита видеоконтента
С ростом визуализации и ориентированных на пользователя гуманизированных подходов в онлайн-образовании [видеоконтент стал одним из самых популярных способов поделиться знаниями со студентами] (https://incora.software/insights/best-video-conferencing-software- прогноз/39). И даже если на вашей платформе не будет кнопки для загрузки видеоматериала, важно уберечь его от скачивания, записи экрана и других вариантов нарушения авторских прав. Конечно, вы также можете добавить на видео водяной знак или идентификатор владельца. Видео помечаются как защищенные авторским правом, даже если они перекодированы с экрана.
Еще один технический вариант — зашифровать видео в вашем программном обеспечении для электронного обучения. Таким образом, даже в случае загрузки плагиатору потребуется ключ шифрования для воспроизведения. Однако для предотвращения ситуаций, когда плагиатор крадет ключ шифрования, более безопасно настроить DRM-шифрование. Это может быть сделано командой разработчиков, с которой вы работаете. Так что, если вы считаете, что это может помочь с безопасностью контента вашего электронного обучения, покажите это руководство своим разработчикам или просто свяжитесь с нами.
Решение Axinom DRM для защиты видеоконтента
Прежде чем использовать нашу службу DRM, нам нужно создать защищенный контент и загрузить его в систему. Это иллюстрируется следующей диаграммой:
По сути, любой контент (в нашем случае видео) должен быть предоставлен для нашего кодировщика с поддержкой DMR. Затем кодировщик отправляет запрос в службу ключей Axinom DRM и получает в ответ один или несколько ключей содержимого. Служба ключей создает свежие ключи и безопасно доставляет их вместе с идентификаторами ключей кодировщику/упаковщику. Кодер/упаковщик шифрует контент и упаковывает его способом, подходящим для адаптивной потоковой передачи с поддержкой DRM, а затем загружает результат на исходный сервер, используя информацию о ключе.
Теперь, когда у нас есть готовый контент, защищенный DRM, мы можем начать работать над нашей службой расшифровки. Чтобы воспроизводить контент, защищенный DRM, игрок должен знать, как читать и воспроизводить защищенное видео. Для этого ему сначала необходимо получить доступ к ключам, которые можно найти в лицензии, которая также отвечает за условия, при которых эти ключи могут использоваться (например, истечение срока действия). Оба они генерируются службой лицензирования Axinom DRM и отправляются игроку, если у него есть правильный токен лицензии.
Этот процесс иллюстрируется следующей схемой:
Теперь давайте попробуем создать приложение для воспроизведения наших демо-видео с защитой DRM.
Примечание: Axinom поддерживает все последние версии следующих браузеров:
- Google Chrome (Widevine)
- Mozilla Firefox (Widevine)
- Microsoft Edge (PlayReady и Widevine)
- Microsoft Internet Explorer (PlayReady)
- Яблочное сафари (честная игра)
Для демонстрации мы будем использовать [ShakaPlayer.] (https://github.com/shaka-project/shaka-player). Теперь, во-первых, давайте создадим нашу страницу index.html:
<голова>
<стиль>
видео#видеоплеер {
ширина: 640 пикселей;
высота: 360 пикселей;
<тело>
Загружается. В случае возникновения проблем смотрите консоль JavaScript.
<дел>
Поддерживаемые браузеры: Google Chrome, Mozilla Firefox, Microsoft Edge, Internet Explorer 11, Apple Safari
Примечание. Демонстрационные видеоролики с несколькими ключами не поддерживаются в IE11.
При первоначальном запуске проверяем, поддерживает ли браузер FairPlay. В тег script нашего index.html мы добавляем следующий код:
$(функция () {
вар $loadingPanel = $("#loadingPanel");
вар $videoListPanel = $("#videoListPanel");
var $videoList = $("#videoList");
var $videoPlayerPanel = $("#videoPlayerPanel");
var $videoPlayer = $("#videoPlayer");
// Специальные переменные FairPlay. Они будут установлены в Safari.
вар isSafariDetected = ложь;
вар FairPlayCertificate = ноль;
var fairPlayCertificateUrl = "https://vtb.axinom.com/FPScert/fairplay.cer";
// Определяем, используем ли мы Safari. Если да, то поддерживается только FairPlay, и мы
// активировать рабочие процессы FairPlay. Это означает, что мы будем:
// * Отображение только видео с поддержкой FairPlay.
// * Загружаем сертификат FairPlay
// * Назначаем пользовательское преобразование InitData для Shaka Player, которое извлекает Content ID
// из манифеста HLS в форме, ожидаемой нашими службами лицензирования FairPlay.
if (typeof WebKitMediaKeys === "function" && WebKitMediaKeys.isTypeSupported("com.apple.fps.1_0", "video/mp4"))
console.log("Обнаружена поддержка FairPlay.");
isSafariDetected = Истина;
Теперь давайте добавим функцию загрузки FairPlayCertificate, если мы используем браузер Safari:
// Специальные функции FairPlay.
функция loadFairPlayCertificate() {
console.log("Запрос сертификата FairPlay от " + fairPlayCertificateUrl)
запрос var = новый XMLHttpRequest();
request.responseType = 'буфер массива';
request.addEventListener («загрузить», onFairPlayCertificateLoaded, false);
request.addEventListener('ошибка', onFairPlayCertificateError, false);
request.open('GET', FairPlayCertificateUrl, true);
request.setRequestHeader('Pragma', 'Cache-Control: no-cache');
request.setRequestHeader("Cache-Control", "max-age=0");
запрос.отправить();
функция onFairPlayCertificateLoaded (событие) {
console.log("Сертификат FairPlay получен.");
переменная запроса = событие.цель;
FairPlayCertificate = новый Uint8Array(request.response);
$loadingPanel.hide();
$videoListPanel.show();
функция onFairPlayCertificateError (событие) {
console.error('Ошибка запроса сертификата FairPlay.');
И, наконец, давайте заполним наш список видео контентом:
$.getJSON("/api/каталог/видео")
.done (функция (видео) {
.done (функция (видео) {
console.log("Сервер предоставил " + videos.length + " видео.");
$.each(видео, функция(индекс, видео) {
// В Safari давайте отображать только те видео, которые поддерживают FairPlay. В других браузерах
// давайте просто покажем все остальное, так как другие наши демонстрационные видеоролики поддерживают и то, и другое
// Widevine и PlayReady.
if ((!video.tags && isSafariDetected) || (video.tags && video.tags.filter(function(tag) {
тег = тег.toLowerCase();
if (isSafariDetected && тег === "честная игра") {
вернуть истину;
} else if (!isSafariDetected && тег !== "честная игра") {
вернуть истину;
} еще {
вернуть ложь;
}).длина == 0)) {
console.log("Видео \"" + video.name + "\" не поддерживается на текущей платформе, скрывая это...");
возврат;
console.log("Видео \"" + video.name + "\" находится по URL-адресу " + video.url);
// Это делает элемент списка для этого видео.
var link = $("");
ссылка.текст(видео.название);
var listItem = $("
$videoList.append(listItem);
link.click (функция () {
игратьВидео(видео);
вернуть ложь;
console.log("Загрузка завершена.");
// Загружаем сертификат FairPlay, если обнаружен Safari.
если (isSafariDetected) {
загрузитьсертификат честной игры();
} еще {
$loadingPanel.hide();
$videoListPanel.show();
.сбой (функция () {
console.log("Вызов API для получения каталога видео не выполнен!");
Теперь давайте создадим простой API каталога, который будет отправлять нам контент, защищенный DMR.
КаталогApi.js:
(функция () {
"использовать строго";
пусть экспресс = требуют("экспресс");
let videoDatabase = require("./VideoDatabase");
модуль.экспорт = {
"createRouter": функция createRouter() {
пусть router = express.Router();
// Этот вызов API возвращает список JSON с базовой информацией обо всех видео на веб-сайте.
router.get("/видео", function processGet(запрос, ответ) {
// Мы не хотим, чтобы наши вызовы API кэшировались.
response.header("Кэш-Контроль", "без кеша");
пусть видеосписок = [];
videoDatabase.getAllVideos().forEach(функция mapVideo(видео) {
// Только имя, URL и необязательные теги списка доступны браузеру.
// Все остальное только для внутреннего использования.
видеоList.push({
"имя": видео.имя,
"url": видео.url,
"теги": видео.теги
ответ.json (видеолист);
обратный маршрутизатор;
VideoDatabase.js будет содержать наш список видео:
пусть все видео = [
// Раскомментируйте и скопируйте и вставьте блок ниже в качестве примера для добавления пользовательского
// видео в список.
"name": "Мое видео 1",
"url": "https://example.com/Manifest.mpd",
"ключи": [
"keyId": "1c817fed-0686-45b6-bce2-d6a4eb873588",
// Следующие записи предназначены для предварительно сгенерированных демо-видео. Чтобы добавить свои видео,
// скопируйте пример видео выше, добавьте в список и настройте поля по мере необходимости.
// Примечание. Демонстрационные видеоролики имеют жестко закодированные лицензионные токены для максимальной простоты использования
// пример приложения. Никогда не делайте этого в рабочей среде — всегда генерируйте новый токен лицензии на
// каждый запрос.
// Примечание: свойство «теги» является необязательным. Демонстрационный проигрыватель использует это для фильтрации видео.
// list -- например, чтобы в Safari отображались только видео, совместимые с FairPlay.
"name": "Демонстрационное видео Axinom - одна клавиша (DASH; cenc)",
"url": "https://media.axprod.net/VTB/DrmQuickStart/AxinomDemoVideo-SingleKey/Encrypted_Cenc/Manifest.mpd",
"licenseToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6eyJ2ZXJzaW9uIjoyLCJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImxpY2Vuc2UiOnsiYWxsb3dfcGVyc2lzdGVuY2UiOnRydWV9LCJjb250ZW50X2tleXNfc291cmNlIjp7ImlubGluZSI6W3siaWQiOiIyMTFhYzFkYy1jOGEyLTQ1NzUtYmFmNy1mYTRiYTU2YzM4YWMiLCJ1c2FnZV9wb2xpY3kiOiJUaGVPbmVQb2xpY3kifV19LCJjb250ZW50X2tleV91c2FnZV9wb2xpY2llcyI6W3sibmFtZSI6IlRoZU9uZVBvbGljeSIsInBsYXlyZWFkeSI6eyJwbGF5X2VuYWJsZXJzIjpbIjc4NjYyN0Q4LUMyQTYtNDRCRS04Rjg4LTA4QUUyNTVCMDFBNyJdfX1dfX0.D9FM9sbTFxBmcCOC8yMHrEtTwm0zy6ejZUCrlJbHz_U",
"name": "Демонстрационное видео Axinom - единый ключ (HLS; cbcs)",
"url": "https://media.axprod.net/VTB/DrmQuickStart/AxinomDemoVideo-SingleKey/Encrypted_Cbcs/Manifest.m3u8",
"licenseToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6eyJ2ZXJzaW9uIjoyLCJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImxpY2Vuc2UiOnsiYWxsb3dfcGVyc2lzdGVuY2UiOnRydWV9LCJjb250ZW50X2tleXNfc291cmNlIjp7ImlubGluZSI6W3siaWQiOiIyMTFhYzFkYy1jOGEyLTQ1NzUtYmFmNy1mYTRiYTU2YzM4YWMiLCJ1c2FnZV9wb2xpY3kiOiJUaGVPbmVQb2xpY3kifV19LCJjb250ZW50X2tleV91c2FnZV9wb2xpY2llcyI6W3sibmFtZSI6IlRoZU9uZVBvbGljeSIsInBsYXlyZWFkeSI6eyJwbGF5X2VuYWJsZXJzIjpbIjc4NjYyN0Q4LUMyQTYtNDRCRS04Rjg4LTA4QUUyNTVCMDFBNyJdfX1dfX0.D9FM9sbTFxBmcCOC8yMHrEtTwm0zy6ejZUCrlJbHz_U",
"теги": ["Честная игра"]
"name": "Демонстрационное видео Axinom - multikey (DASH; cenc)",
"url": "https://media.axprod.net/VTB/DrmQuickStart/AxinomDemoVideo-MultiKey/Encrypted_Cenc/Manifest.mpd",
"licenseToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6eyJ2ZXJzaW9uIjoyLCJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImxpY2Vuc2UiOnsiYWxsb3dfcGVyc2lzdGVuY2UiOnRydWV9LCJjb250ZW50X2tleXNfc291cmNlIjp7ImlubGluZSI6W3siaWQiOiJmM2Q1ODhjNy1jMTdhLTQwMzMtOTAzNS04ZGIzMTczOTBiZTYiLCJ1c2FnZV9wb2xpY3kiOiJUaGVPbmVQb2xpY3kifSx7ImlkIjoiNDRiMThhMzItNmQzNi00OTlkLThiOTMtYTIwZjk0OGFjNWYyIiwidXNhZ2VfcG9saWN5IjoiVGhlT25lUG9saWN5In0seyJpZCI6ImFlNmU4N2UyLTNjM2MtNDZkMS04ZTlkLWVmNGM0NjFkNDY4MSIsInVzYWdlX3BvbGljeSI6IlRoZU9uZVBvbGljeSJ9XX0sImNvbnRlbnRfa2V5X3VzYWdlX3BvbGljaWVzIjpbeyJuYW1lIjoiVGhlT25lUG9saWN5IiwicGxheXJlYWR5Ijp7InBsYXlfZW5hYmxlcnMiOlsiNzg2NjI3RDgtQzJBNi00NEJFLThGODgtMDhBRTI1NUIwMUE3Il19fV19fQ.DpwBd1ax4Z7P0cCOZ7ZJMotqVWfLFCj2DYdH37xjGxM",
"name": "Демонстрационное видео Axinom - мультиключ (HLS; cbcs)",
"url": "https://media.axprod.net/VTB/DrmQuickStart/AxinomDemoVideo-MultiKey/Encrypted_Cbcs/Manifest.m3u8",
"licenseToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6eyJ2ZXJzaW9uIjoyLCJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImxpY2Vuc2UiOnsiYWxsb3dfcGVyc2lzdGVuY2UiOnRydWV9LCJjb250ZW50X2tleXNfc291cmNlIjp7ImlubGluZSI6W3siaWQiOiJmM2Q1ODhjNy1jMTdhLTQwMzMtOTAzNS04ZGIzMTczOTBiZTYiLCJ1c2FnZV9wb2xpY3kiOiJUaGVPbmVQb2xpY3kifSx7ImlkIjoiNDRiMThhMzItNmQzNi00OTlkLThiOTMtYTIwZjk0OGFjNWYyIiwidXNhZ2VfcG9saWN5IjoiVGhlT25lUG9saWN5In0seyJpZCI6ImFlNmU4N2UyLTNjM2MtNDZkMS04ZTlkLWVmNGM0NjFkNDY4MSIsInVzYWdlX3BvbGljeSI6IlRoZU9uZVBvbGljeSJ9XX0sImNvbnRlbnRfa2V5X3VzYWdlX3BvbGljaWVzIjpbeyJuYW1lIjoiVGhlT25lUG9saWN5IiwicGxheXJlYWR5Ijp7InBsYXlfZW5hYmxlcnMiOlsiNzg2NjI3RDgtQzJBNi00NEJFLThGODgtMDhBRTI1NUIwMUE3Il19fV19fQ.DpwBd1ax4Z7P0cCOZ7ZJMotqVWfLFCj2DYdH37xjGxM",
"теги": ["Честная игра"]
Простая проверка всех необходимых данных в списке видео:
// Проверяет наличие в видео всей критической информации.
// Автоматически выполняет проверки работоспособности, чтобы избежать ошибок в приведенном выше списке.
функция verifyVideoIntegrity (видео) {
если (!видео)
throw new Error("Ожидалось видео, но его не было.");
если (!видео.название || !видео.название.длина)
throw new Error("У видео отсутствует название.");
console.log("Проверка целостности определения видео: " + video.name);
если (!video.url || !video.url.length)
throw new Error("У видео отсутствует URL-адрес.");
// Должен существовать либо жестко заданный токен лицензии, либо структура ключей. Не оба.
если (video.licenseToken && video.keys)
throw new Error("В видео есть как жестко заданный лицензионный токен, так и список ключей контента - выберите только один.");
если (!video.licenseToken && !video.keys)
throw new Error("В видео отсутствует список ключей содержимого.");
если (видео.ключи) {
если (!video.keys.length)
throw new Error("Список ключей контента для этого видео пуст.");
// Убедитесь, что каждый элемент в списке ключей имеет все необходимые данные.
video.keys.forEach (функция verifyKey (элемент) {
если (!item.keyId)
throw new Error("В ключе содержимого отсутствует идентификатор ключа.");
// Проверяем все видео при запуске.
allVideos.forEach (проверить целостность видео);
И, наконец, экспорт модуля API каталога:
модуль.экспорт = {
"getAllVideos": функция getAllVideos() {
вернуть все видео;
"getVideoByName": функция getVideoByName(имя) {
вернуть allVideos.find (функция фильтра (элемент) {
вернуть item.name === имя;
Теперь, когда мы запустим наш index.html в Chrome, мы увидим следующую страницу:
И консоль разработчика будет выглядеть так:
Теперь давайте проиграем видео, которое мы загрузили в наш плеер. Давайте добавим функцию playVideo, которая будет вызываться, когда мы нажимаем видео из списка.
При нажатии на видео нам нужно получить licenseToken от нашего сервиса авторизации:
$.getJSON("/api/авторизация/" + encodeURIComponent(video.name))
.done (функция (licenseToken) {
// Мы получили лицензионный токен! Мы готовы начать воспроизведение.
// Мы просто передаем его игроку, а он позаботится обо всем остальном.
Теперь давайте посмотрим на нашего поставщика лицензий:
// Этот вызов API возвращает токен лицензии для воспроизведения видео.
// Веб-приложение предоставляет имя видео в качестве параметра в URL-адресе.
router.get("/:videoName", function processGet(запрос, ответ) {
// Мы не хотим, чтобы наши вызовы API кэшировались.
response.header("Кэш-Контроль", "без кеша");
let video = videoDatabase.getVideoByName(request.params.videoName);
если (!видео) {
response.status(NO_SUCH_VIDEO_STATUS_CODE).send("Нет такого видео");
возврат;
// TODO: Проверьте здесь, действительно ли пользователь авторизован для просмотра этого видео. Например, вы можете
// проверяем базу данных покупок, чтобы узнать, совершил ли текущий авторизованный пользователь релевантную покупку
// для этого продукта. Однако в демонстрационных целях всем всегда разрешено смотреть каждое видео.
если (видео.licenseToken) {
// Если у видео жестко запрограммирован токен лицензии, просто дайте его всем вызывающим абонентам.
// Строго только для демонстрационных целей — никогда не делайте этого в реальном мире.
ответ.json(видео.licenseToken);
возврат;
Как вы можете видеть в приведенном выше коде, если у видео есть токен лицензии, мы просто возвращаем его в браузер, но здесь можно выполнить более сложные проверки.
Если у нас нет токена, мы можем сгенерировать его самостоятельно. Во-первых, мы создаем наш сервис менеджера секретов — SecretManagement.js:
(функция () {
"использовать строго";
константа COMMUNICATION_KEY_LENGTH_IN_BYTES = 32;
const SECRETS_FILE_NAME = "Secrets.json";
// Глобальная переменная с загруженными секретами.
пусть секреты = ноль;
модуль.экспорт = {
"getSecrets": функция getSecrets() {
вернуть секреты;
"areSecretsAvailable": функция areSecretsAvailable() {
вернуть секреты == NULL!;
// Попытка загрузить секреты из Secrets.json, если файл существует.
// Ничего страшного, если он не существует — жестко закодированные образцы видео все равно будут работать.
"tryLoadSecrets": функция tryLoadSecrets() {
пусть фс = требуют ("фс");
если (!fs.existsSync(SECRETS_FILE_NAME)) {
console.log("Файл " + SECRETS_FILE_NAME + " не найден - можно просматривать только встроенные примеры видео.");
возврат;
} еще {
console.log("Загрузка " + SECRETS_FILE_NAME + " файл.");
секреты = требуют("./" + SECRETS_FILE_NAME);
если (!secrets.communicationKeyId)
выдать новую ошибку (SECRETS_FILE_NAME + "проверка не удалась: отсутствует поле CommunicationKeyId.");
если (!секреты.коммуникационныйКлюч)
выдать новую ошибку (ИМЯ_ФАЙЛА_SECRETS + "проверка не удалась: поле коммуникационного ключа отсутствует.");
var CommunicationKeyBuffer = Buffer.from(secrets.communicationKey, 'base64');
если (связьKeyBuffer.length !== COMMUNICATION_KEY_LENGTH_IN_BYTES)
выдать новую ошибку (ИМЯ_ФАЙЛА_SECRETS + "проверка не удалась: ключ связи не содержит " + COMMUNICATION_KEY_LENGTH_IN_BYTES + " байтов данных в кодировке base64.");
если (secrets.communicationKeyId === "00000000-0000-0000-0000-000000000000"
|| secrets.communicationKey === "00000000000000000000000000000000000000000w==")
throw new Error("Вам нужно заменить примеры значений в " + SECRETS_FILE_NAME + " своими собственными!");
Мы храним и загружаем наши секреты в локальный файл Secrets.json. Теперь мы можем загрузить их в наш провайдер лицензий:
если (!secretManagement.areSecretsAvailable()) {
console.log("ОШИБКА: Вы должны настроить файл секретов для создания токенов лицензии.");
response.status(NEED_TO_KNOW_SECRETS_STATUS_CODE)
.send("Вы должны настроить файл секретов для создания токенов лицензии.");
возврат;
пусть секреты = secretManagement.getSecrets();
пусть CommunicationKeyAsBuffer = Buffer.from(secrets.communicationKey, "base64");
// Мы разрешаем использовать этот токен в течение плюс-минус 24 часов. Это позволяет много
// сдвиг часов, так как ваш демонстрационный сервер может неправильно синхронизироваться в режиме реального времени по всему миру.
// В производственных сценариях следует более строго ограничивать использование токена лицензии.
// Определенное здесь ограничение по времени применяется как к токену лицензии, так и к любым сгенерированным лицензиям,
// хотя можно управлять ими отдельно в ситуациях, когда это необходимо.
пусть сейчас = момент();
let validFrom = now.clone().subtract(1, "days");
пусть validTo = now.clone (). Добавить (1, «дни»);
// Подробную информацию об этих полях см. в документации Axinom DRM.
// Существует много возможностей для дальнейшей настройки лицензионного токена - настройки
// показанный здесь только самый минимум для создания лицензионного токена, подходящего для реального использования.
пусть сообщение = {
"тип": "entitlement_message",
"версия": 2,
"лицензия": {
"start_datetime": validFrom.toISOString(),
"expiration_datetime": validTo.toISOString(),
"allow_persistence": правда
// Список ключей будет заполняться отдельно следующим блоком кода.
"content_keys_source": {
"в линию": [
// Конфигурация лицензии должна быть максимально допустимой для целей данного руководства.
// По этой причине ниже некоторые ограничения, относящиеся к PlayReady, ослаблены.
// Нет необходимости ослаблять специальные ограничения Widevine или FairPlay по умолчанию.
"content_key_usage_policies": [
"имя": "Политика А",
"готово к игре": {
// Разрешить воспроизведение на непроизводственных устройствах.
"минимальный_уровень_безопасности_устройства": 150,
// Разрешить воспроизведение на виртуальных машинах.
"play_enablers": [
"786627D8-C2A6-44BE-8F88-08AE255B01A7"
Теперь мы встраиваем информацию о ключе контента (идентификаторы и политики использования) в токен лицензии.
video.keys.forEach (функция (ключ) {
// Идентификатор ключа требуется всегда. В этой демонстрации мы также будем ссылаться на ранее определенный
// политика использования ключей.
пусть inlineKey = {
«идентификатор»: key.keyId,
"usage_policy": "Политика А"
message.content_keys_source.inline.push(inlineKey);
// Подробную информацию об этих полях см. в документации Axinom DRM.
пусть конверт = {
"версия": 1,
"com_key_id": секреты.communicationKeyId,
"сообщение": сообщение,
"begin_date": validFrom.toISOString(),
"expiration_date": validTo.toISOString()
console.log("Создание токена лицензии с полезной нагрузкой: " + JSON.stringify(envelope));
// Токен лицензии должен иметь цифровую подпись, чтобы доказать, что он получен от службы токенов.
пусть licenseToken = jwt.sign (конверт, коммуникацияKeyAsBuffer, {
"алгоритм": "HS256",
«нотаймштамп»: правда
ответ.json(licenseToken);
Теперь мы можем вызвать этот сервис для получения токена при клике на видео:
$.getJSON("/api/авторизация/" + encodeURIComponent(video.name))
.done (функция (licenseToken) {
// Мы получили лицензионный токен! Мы готовы начать воспроизведение.
// Мы просто передаем его игроку, а он позаботится обо всем остальном.
console.log("Запуск воспроизведения плеера Shaka с токеном лицензии: " + licenseToken)
После того, как мы получим токен, мы настроим наш Shaka Player и при необходимости загрузим FairPlayCertificate:
var player = новый shaka.Player($videoPlayer[0]);
// Прикрепляем плеер к окну, чтобы упростить доступ к нему в консоли JS.
окно.игрок = игрок;
// Прослушивание событий ошибок.
player.addEventListener('ошибка', onErrorEvent);
// Настройте службы лицензирования Axinom DRM.
player.configure({
ДРМ: {
серверы: {
'com.widevine.alpha': 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
«com.microsoft.playready»: «https://drm-playready-licensing.axtest.net/AcquireLicense»,
«com.apple.fps.1_0»: «https://drm-fairplay-licensing.axtest.net/AcquireLicense»
если (isSafariDetected === true) {
player.configure('drm.advanced.com\.apple\.fps\.1_0.serverCertificate', fairPlayCertificate);
Теперь мы просто устанавливаем наш лицензионный токен и загружаем видео:
// Добавляем в заголовок заголовок "X-AxDRM-Message", содержащий токен лицензии
// всех запросов лицензии.
player.getNetworkingEngine().registerRequestFilter(функция(тип, запрос) {
если (тип == shaka.net.NetworkingEngine.RequestType.LICENSE) {
// Это конкретное имя заголовка и значение, которое хочет сервер:
request.headers['X-AxDRM-Message'] = licenseToken;
// Попытка загрузить манифест. Это асинхронный процесс.
player.load(video.url).then(function() {
// Это выполняется, если асинхронная загрузка прошла успешно.
// onError() выполняется, если асинхронная загрузка не удалась.
console.log('Видео загружено!');
}).поймать (при ошибке);
А теперь попробуем наш Плеер — при нажатии на видео из списка мы видим следующее содержимое:
Итак, подводя итог, давайте пройдемся по шагам, которые происходят при интеграции Axinom DRM:
- Код JavaScript на стороне браузера сначала проверяет, поддерживает ли браузер FairPlay.
- Если FairPlay включен, тестовый сертификат Axinom FairPlay загружается с сервера Axinom, а встроенный проигрыватель настраивается для поддержки FairPlay.
- Для получения списка фильмов активируется API Каталога.
- Видео возвращаются через API.
- Когда пользователь щелкает ссылку на видео, чтобы начать его воспроизведение, происходит следующее.
- Клиент запрашивает токен лицензии. В рабочей среде этот сервис также должен авторизовать пользователя.
- Служба предоставления прав предоставляет маркер.
- После получения токена код активирует встроенный проигрыватель Shaka Player и предоставляет URL-адрес видео и конфигурацию DRM. Остальную часть процесса будет контролировать код игрока.
- Если видео защищено, плеер запрашивает лицензию у сервиса, а также прикрепляет к ней лицензионный токен.
- Если авторизация прошла успешно, служба лицензий возвращает лицензию на основе информации в токене.
- Начинается воспроизведение (при условии, что ключи содержимого в лицензии указаны правильно и соблюдены правила воспроизведения).
Подведение итогов
При разработке программного обеспечения для электронного обучения необходимо разработать стратегию защиты контента. Очевидно, что если вы не будете защищать онлайн-курсы на своей платформе, они уже не будут такими уникальными и эксклюзивными. И в результате это может уменьшить прибыль. Итак, чтобы оставаться на плаву и оставаться желанной платформой для любого учащегося, убедитесь, что вы предлагаете профессиональные материалы на заказ и защищаете их от плагиата.
Впервые опубликовано [здесь] (https://incora.software/insights/eLearning-content-security/101)
Оригинал