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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    new DRMContentData(metadata_bytes)

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

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

    Для обработки этой ошибки загрузите модуль Flash 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 обрабатывает обновление модуля Flash 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. Если происходит сбой проверки подлинности, приложение должно возвращаться к выполнению действия 9. Убедитесь, что в приложении предусмотрен механизм для обработки и ограничения повторяющихся сбоев проверки подлинности. Например, после трех попыток отображается сообщение о сбое проверки подлинности и невозможности воспроизведения содержимого.

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

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.FORCE_REFRESH)

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

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

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

  13. Воспроизведите видео. Для этого создайте объект 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); 

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

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

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

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

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

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

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

  • Событие StatusEvent

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

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

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

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

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

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

  1. Получите бинарные метаданные для упакованного содержимого. При использовании базового средства упаковки Java Flash 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 является userNameAndPassword, то перед загрузкой ваучера выполните проверку подлинности пользователя на сервере управления правами на мультимедийное содержимое. Свойства serverURL и domain объекта DRMContentData могут быть переданы методу authenticate() класса DRMManager вместе с учетными данными пользователя.

  7. Функция обратного вызова onPlayStatus() вызывается, когда выполнен разбор файла. Если функция onDRMContentData() не была вызвана, то файл не содержит метаданных, требуемых для получения ваучера. То, что функция не была вызвана, также может означать, что этот файл не защищен Flash 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(); 
    } 
} 
}