Описание технологического процесса защищенного содержимого

Flash Player 10.1 и более поздних версий, Adobe AIR 2.0 и более поздних версий

Важная информация . В состав Flash Player 11.5 и более поздних версий уже включен модуль Adobe Access, поэтому обновление (посредством метода SystemUpdater.update(SystemUpdaterType.DRM) ) не требуется. Это относится к следующим браузерам и платформам:

  • Компонент Flash Player 11.5 ActiveX — для всех платформ, за исключением Internet Explorer на Windows 8 на компьютерах с процессорами Intel

  • Плагин Flash Player 11.5 — для всех браузеров;

  • Adobe AIR (для настольных и мобильных систем).

Это означает, что обновление все же требуется в следующих случаях:

  • Internet Explorer на Windows 8; на компьютерах с процессорами Intel

  • Flash Player 11.4 и более старых версий, за исключением браузера Google Chrome версии 22 и более поздней (для всех платформ) или 21 и более поздней (для Windows).

Примечание. Вызов метода SystemUpdater.update(SystemUpdaterType.DRM) в системах с Flash Player 11.5 и более поздних версий не приведет к ошибкам, и при этом ничего не будет загружено.

Следующий рабочий процесс высокого уровня демонстрирует, как приложение может получать и воспроизводить защищенное содержимое. В этом рабочем процессе подразумевается, что приложение создано специально для воспроизведения содержимого, защищенного Adobe Access:

  1. Получите метаданные содержимого.

  2. При необходимости обработайте обновления в проигрывателе Flash Player.

  3. Проверьте, доступна ли лицензия локально. Если доступна, загрузите ее и перейдите к действию 7. Если нет, перейдите к действию 4.

  4. Проверьте, требуется ли проверка подлинности. Если нет, перейдите к действию 7.

  5. Если проверка подлинности требуется, получите учетные данные для проверки подлинности у пользователя и передайте их на сервер лицензий.

  6. Если требуется регистрация домена, выполните ее (в AIR 3.0 и более поздних версиях).

  7. После выполнения проверки подлинности загрузите лицензию с сервера.

  8. Воспроизведите содержимое.

Если операция выполнена без ошибок и пользователь авторизован для просмотра содержимого, объект NetStream отправляет объект DRMStatusEvent. В программе начинается воспроизведение. Объект DRMStatusEvent содержит необходимую информацию о ваучере, которая определяет политику и разрешения для пользователя. Например, в нем хранится информация о том, может ли содержимое быть доступно в автономном режиме, или информация об окончании срока действия лицензии. Эти данные могут использоваться приложением для сообщения пользователю статуса его разрешения. Например, в приложении может отображаться число дней, оставшихся до конца периода просмотра.

Если пользователю разрешен доступ в автономном режиме, ваучер кэшируется и зашифрованное содержимое загружается на компьютер пользователя. Содержимое доступно в течение срока, определяемого периодом кэширования лицензии. Свойство события detail содержит запись "DRM.voucherObtained" . Приложение определяет, где хранить содержимое в системе пользователя, чтобы оно было доступно в автономном режиме. Можно также предварительно загрузить ваучеры с помощью класса DRMManager.

Примечание. Кэширование и предварительная загрузка ваучеров поддерживается как в AIR, так и в Flash Player. Однако загрузка и хранение зашифрованного содержимого поддерживается только в AIR.

Ошибки обрабатывает исключительно приложение. Это касается и случаев, когда пользовать вводит верные учетные данные, но ваучер, защищающий зашифрованное содержимое, запрещает доступ к содержимому. Например, пользователь, прошедший проверку подлинности, не может получать доступ к содержимому, если не оплачены права доступа. Такая ситуация может настать, если два зарегистрированных участника пытаются обратиться к содержимому издателя, за которое заплатил только один из них. Приложение должно сообщить пользователю об ошибке и предложить варианты действий. Типичным предлагаемым вариантом являются инструкции по регистрации и оплате просмотра.

Подробный технологический процесс API-интерфейса

С помощью этой последовательности действий приводится более подробное описание технологического процесса защищенного содержимого. В этом рабочем процессе описаны API-интерфейсы, используемые специально для воспроизведения содержимого, защищенного Adobe Access.

  1. С использованием объекта URLLoader загрузите байты файла метаданных защищенного содержимого. Задайте этот объект для переменной, например metadata_bytes .

    Для всего содержимого, управляемого Adobe Access, предусмотрены метаданные Adobe Access. При создании пакета содержимого эти метаданные можно сохранить в качестве отдельного файла метаданных (.metadata) наряду с содержимым. Дополнительные сведения см. в документации по Adobe Access.

  2. Создайте экземпляр DRMContentData. Поместите этот код в блок try-catch:

    new DRMContentData( metadata_bytes )

    где metadata_bytes — объект URLLoader, полученный в действии 1.

  3. (только для проигрывателя Flash Player) Среда выполнения проверяет наличие модуля Adobe Access. Если он не обнаружен, выдается исключение IllegalOperationError, содержащее ошибку DRMErrorEvent с кодом 3344 или DRMErrorEvent с кодом 3343.

    Для обработки этой ошибки загрузите модуль Adobe Access с помощью API-интерфейса SystemUpdater. По завершении загрузки модуля объект SystemUpdater отправляет событие COMPLETE. Включите прослушиватель для этого события, который выполняет возврат к действию 2 при отправке этого события. Эти действия иллюстрирует следующий код:

    flash.system.SystemUpdater.addEventListener(Event.COMPLETE, updateCompleteHandler); 
    flash.system.SystemUpdater.update(flash.system.SystemUpdaterType.DRM)
    private function updateCompleteHandler (event:Event):void { 
        /*redo step 2*/ 
        drmContentData = new DRMContentData(metadata_bytes); 
    } 

    Если необходимо обновить сам проигрыватель, отправляется событие состояния. Дополнительные сведения об обработке этого события см. в разделе « Прослушивание события обновления ».

    Примечание. В приложениях AIR установщик AIR обрабатывает обновление модуля Adobe Access и требуемых обновлений среды выполнения.
  4. Создайте прослушиватели для прослушивания событий DRMStatusEvent и DRMErrorEvent, отправляемых из объекта DRMManager:

    DRMManager.addEventListener(DRMStatusEvent.DRM_STATUS, onDRMStatus); 
    DRMManager.addEventListener(DRMErrorEvent.DRM_ERROR, onDRMError);

    В прослушивателе DRMStatusEvent проверьте, что ваучер действителен (не является нулевым). В прослушивателе DRMErrorEvent обработайте события DRMErrorEvent. См. разделы « Использование класса DRMStatusEvent » и « Использование класса DRMErrorEvent ».

  5. Загрузите ваучер (лицензию), необходимый для воспроизведения содержимого.

    Сначала попробуйте загрузить локально сохраненную лицензию для воспроизведения содержимого:

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.LOCAL_ONLY)

    По завершении загрузки объект DRMManager отправляет событие DRMStatusEvent.DRM_Status .

  6. Если объект DRMVoucher не является нулевым, ваучер действителен. Перейдите к действию 13.

  7. Если объект DRMVoucher является нулевым, проверьте метод проверки подлинности, требуемый политикой для этого содержимого. Используйте свойство DRMContentData.authenticationMethod .

  8. Если методом проверки подлинности является ANONYMOUS , перейдите к действию 13.

  9. Если методом проверки подлинности является USERNAME_AND_PASSWORD , приложение должно предоставлять механизм, позволяющий пользователю вводить учетные данные. Передайте эти учетные данные на сервер лицензий для проверки подлинности пользователя:

    DRMManager.authenticate(metadata.serverURL, metadata.domain, username, password)

    Объект DRMManager отправляет событие DRMAuthenticationErrorEvent , если проверка подлинности выполнена неудачно, или событие DRMAuthenticationCompleteEvent , если проверка подлинности выполнена удачно. Создайте прослушиватели для этих событий.

  10. Если для метода проверки подлинности задано значение UNKNOWN , необходимо применить пользовательский метод. В данном случае поставщик содержимого предусмотрел выполнение внешней проверки подлинности без использования API-интерфейсов ActionScript 3.0. Пользовательская процедура проверки подлинности должна генерировать маркер авторизации, который можно передать методу DRMManager.setAuthenticationToken() .

  11. Если происходит сбой проверки подлинности, приложение должно возвращаться к выполнению действия 9. Убедитесь, что в приложении предусмотрен механизм для обработки и ограничения повторяющихся сбоев проверки подлинности. Например, после трех попыток отображается сообщение о сбое проверки подлинности и невозможности воспроизведения содержимого.

  12. Чтобы использовать сохраненную метку вместо приглашения к вводу учетных данных, задайте метку с помощью метода DRMManager.setAuthenticationToken() . После этого лицензия загружается с сервера лицензий и содержимое воспроизводится, как в действии 8.

  13. (необязательно) Если проверка подлинности выполнена, можно получить метку проверки подлинности, которая представляет собой байтовый массив, кэшированный в памяти. Получите эту метку с помощью свойства DRMAuthenticationCompleteEvent.token . Можно сохранить и использовать метку проверки подлинности, чтобы пользователям не нужно было постоянно вводить учетные данные для этого содержимого. Сервер лицензий определяет период, в течение которого метка проверки подлинности действительна.

  14. Если проверка подлинности выполнена загрузите лицензию с сервера лицензий:

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.FORCE_REFRESH)

    По завершении загрузки объект DRMManager отправляет событие DRMStatusEvent.DRM_STATUS. Прослушивайте это событие, при его отправке можно воспроизвести содержимое.

  15. Воспроизведите видео. Для этого создайте объект NetStream и вызовите метод play() :

    stream = new NetStream(connection); 
    stream.addEventListener(DRMStatusEvent.DRM _STATUS, drmStatusHandler); 
    stream.addEventListener(DRMErrorEvent.DRM_ERROR, drmErrorHandler); 
    stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
    stream.client = new CustomClient(); 
    video.attachNetStream(stream); 
    stream.play(videoURL); 

DRMContentData и объекты сеансов

Когда создается экземпляр DRMContentData , он используется как объект сеанса, ссылающийся на модуль Flash Player DRM. Все API-интерфейсы DRMManager , получаемые этим экземпляром DRMContentData будут использовать данный модуль DRM. Однако существует два API-интерфейса DRMManager , которые не используют экземпляр DRMContentData . Они перечислены ниже.
  1. authenticate()

  2. setAuthenticationToken()

Так как отсутствует связанный экземпляр DRMContentData , при вызове этих API-интерфейсов DRMManager будет использоваться последний модуль DRM с диска. Это может вызывать проблемы, если в середине рабочего процесса DRM приложения произойдет обновление модуля DRM. Рассмотрим следующую ситуацию.
  1. Приложение создает объект DRMContentData с именем contentData1 , который использует модуль DRM с именем AdobeCP1 .

  2. Приложение вызывает метод DRMManager.authenticate(contentData1.serverURL,...) .

  3. Приложение вызывает метод DRMManager.loadVoucher(contentData1, ...) .

Если обновление модуля DRM произойдет, прежде чем приложение перейдет к шагу 2, то метод DRMManager.authenticate() будет выполнять проверку подлинности с помощью модуля DRM с именем AdobeCP2 . Метод loadVoucher() в шаге 3 вернет ошибку, так как он будет по-прежнему использовать модуль DRM с именем AdobeCP1 . Обновление может произойти, если другое приложение вызовет обновление модуля DRM. Чтобы этого не происходило, можно вызвать обновление модуля DRM при запуске приложения.

События, связанные с DRM

Среда выполнения отправляет многочисленные события, когда в приложении предпринимается попытка воспроизвести защищенное содержимое:

  • Событие DRMDeviceGroupErrorEvent (только для AIR), отправляемое DRMManager

  • Событие DRMAuthenticateEvent (только для AIR), отправляемое объектом NetStream

  • Событие DRMAuthenticationCompleteEvent, отправляемое объектом DRMManager

  • Событие DRMAuthenticationErrorEvent, отправляемое объектом DRMManager

  • Событие DRMErrorEvent, отправляемое объектами NetStream и DRMManager

  • Событие DRMStatusEvent, отправляемое объектами NetStream и DRMManager

  • Событие StatusEvent

  • Событие NetStatusEvent. См. раздел « Прослушивание события обновления ».

Для поддержки содержимого, защищенного Adobe Access, добавьте прослушиватели событий для обработки событий DRM.

Предварительная загрузка ваучеров для автономного воспроизведения

Можно предварительно загрузить ваучеры (лицензии), требуемые для воспроизведения содержимого, защищенного Adobe Access. Предварительно загруженные ваучеры дают пользователям возможность просматривать содержимое независимо от наличия доступа к Интернету. (Но для самого процесса предварительной загрузки требуется подключение к Интернету.) Для предварительной загрузки ваучеров можно использовать метод preloadEmbeddedMetadata() класса NetStream и класс DRMManager. В среде AIR 2.0 и более поздней версии для непосредственной предварительной загрузки ваучеров можно использовать объект DRMContentData. Этот метод является предпочтительным, поскольку он позволяет обновлять объект DRMContentData независимо от содержимого. (Метод preloadEmbeddedData() извлекает объект DRMContentData из содержимого.)

Использование объекта DRMContentData

Следующие действия описывают рабочий процесс предварительной загрузки ваучера для защищенного файла мультимедиа с использованием объекта DRMContentData.

  1. Получите бинарные метаданные для упакованного содержимого. При использовании базового средства упаковки Java Adobe Access этот файл метаданных автоматически создается с расширением .metadata . Эти метаданные можно загрузить, к примеру, с помощью класса URLLoader.

  2. Создайте объект DRMContentData, передав метаданные функции конструктора:

    var drmData:DRMContentData = new DRMContentData( metadata );
  3. Остальные действия аналогичны действиям в технологическом процессе, описанном в разделе « Описание технологического процесса защищенного содержимого ».

Использование метода preloadEmbeddedMetadata()

Следующие действия описывают рабочий процесс предварительной загрузки ваучера для DRM-защищенного файла мультимедиа с использованием метода preloadEmbeddedMetadata() .

  1. Загрузите и сохраните мультимедийный файл. (Метаданные DRM могут быть предварительно загружены только из локально сохраненных файлов.)

  2. Создайте объекты NetConnection и NetStream, обеспечив реализацию функций обратного вызова onDRMContentData() и onPlayStatus() в клиентском объекте NetStream.

  3. Создайте объект NetStreamPlayOptions и установите в свойстве stream адрес URL для локального мультимедийного файла.

  4. Вызовите метод preloadEmbeddedMetadata() класса NetStream, передав ему объект NetStreamPlayOptions, идентифицирующий мультимедийный файл для разбора.

  5. Если мультимедийный файл содержит метаданные DRM, то вызывается функция onDRMContentData() . Метаданные передаются этой функции в виде объекта DRMContentData.

  6. Используйте объект DRMContentData для получения ваучера с помощью метода loadVoucher() класса DRMManager.

    Если свойство authenticationMethod объекта DRMContentData имеет значение flash.net.drm.AuthenticationMethod.USERNAME_AND_PASSWORD , то перед загрузкой ваучера выполните проверку подлинности пользователя на сервере управления правами на мультимедийное содержимое. Свойства serverURL и domain объекта DRMContentData могут быть переданы методу authenticate() класса DRMManager вместе с учетными данными пользователя.

  7. Функция обратного вызова onPlayStatus() вызывается, когда выполнен разбор файла. Если функция onDRMContentData() не была вызвана, то файл не содержит метаданных, требуемых для получения ваучера. То, что функция не была вызвана, также может означать, что этот файл не защищен Adobe Access.

Следующий пример кода для среды AIR показывает способ начальной загрузки ваучера для локального файла мультимедиа:

package 
{ 
import flash.display.Sprite; 
import flash.events.DRMAuthenticationCompleteEvent; 
import flash.events.DRMAuthenticationErrorEvent; 
import flash.events.DRMErrorEvent;   
import flash.ev ents.DRMStatusEvent; 
import flash.events.NetStatusEvent; 
import flash.net.NetConnection; 
import flash.net.NetStream; 
import flash.net.NetStreamPlayOptions; 
import flash.net.drm.AuthenticationMethod; 
import flash.net.drm.DRMContentData; 
import flash.net.drm.DRMManager; 
import flash.net.drm.LoadVoucherSetting;   
public class DRMPreloader extends Sprite  
{ 
     private var videoURL:String = "app-storage:/video.flv"; 
    private var userName:String = "user"; 
    private var password:String = "password";  
    private var preloadConnection:NetConnection; 
    private var preloadStream:NetStream; 
    private var drmManager:DRMManager = DRMManager.getDRMManager(); 
    private var drmContentData:DRMContentData; 
    public function DRMPreloader():void { 
        drmManager.addEventListener( 
            DRMAuthenticationCompleteEvent.AUTHENTICATION_COMPLETE, 
            onAuthenticationComplete); 
        drmManager.addEventListener(DRMAuthenticationErrorEvent.AUTHENTICATION_ERROR, 
            onAuthenticationError);             
        drmManager.addEventListener(DRMStatusEvent.DRM_STATUS, onDRMStatus); 
        drmManager.addEventListener(DRMErrorEvent.DRM_ERROR, onDRMError); 
        preloadConnection = new NetConnection(); 
        preloadConnection.addEventListener(NetStatusEvent.NET_STATUS, onConnect); 
        preloadConnection.connect(null);            
    } 
 
    private function onConnect( event:NetStatusEvent ):void 
    { 
        preloadMetadata(); 
    } 
    private function preloadMetadata():void 
    { 
        preloadStream = new NetStream( preloadConnection ); 
        preloadStream.client = this; 
        var options:NetStreamPlayOptions = new NetStreamPlayOptions(); 
        options.streamName = videoURL; 
        preloadStream.preloadEmbeddedData( options );                         
    }     
    public function onDRMContentData( drmMetadata:DRMContentData ):void 
    { 
        drmContentData = drmMetadata; 
        if ( drmMetadata.authenticationMethod == AuthenticationMethod.USERNAME_AND_PASSWORD ) 
        { 
            authenticateUser(); 
        } 
        else 
            { 
                getVoucher(); 
            } 
    } 
    private function getVoucher():void 
    { 
        drmManager.loadVoucher( drmContentData, LoadVoucherSetting.ALLOW_SERVER ); 
    } 
 
    private function authenticateUser():void 
    { 
        drmManager.authenticate( drmContentData.serverURL, drmContentData.domain, userName, password ); 
    } 
    private function onAuthenticationError( event:DRMAuthenticationErrorEvent ):void 
    { 
        trace( "Authentication error: " + event.errorID + ", " + event.subErrorID ); 
    } 
 
    private function onAuthenticationComplete( event:DRMAuthenticationCompleteEvent ):void 
    { 
        trace( "Authenticated to: " + event.serverURL + ", domain: " + event.domain ); 
        getVoucher(); 
    } 
    private function onDRMStatus( event:DRMStatusEvent ):void 
    { 
        trace( "DRM Status: " + event.detail); 
        trace("--Voucher allows offline playback = " + event.isAvailableOffline ); 
        trace("--Voucher already cached          = " + event.isLocal ); 
        trace("--Voucher required authentication = " + !event.isAnonymous ); 
    } 
    private function onDRMError( event:DRMErrorEvent ):void 
    { 
        trace( "DRM error event: " + event.errorID + ", " + event.subErrorID + ", " + event.text ); 
    } 
    public function onPlayStatus( info:Object ):void 
    { 
        preloadStream.close(); 
    } 
} 
}