Nozioni fondamentali sul flusso di contenuto protetto

Flash Player 10.1 e versioni successive, Adobe AIR 2.0 e versioni successive

Importante : in Flash Player 11.5 e versioni successive, il modulo Adobe Access è integrato, quindi la fase di aggiornamento (la chiamata di SystemUpdater.update(SystemUpdaterType.DRM) ) non è necessaria. Questo vale per i browser e le piattaforme seguenti:

  • Controllo ActiveX Flash Player 11.5, per tutte le piattaforme eccetto Internet Explorer in Windows 8 su processori Intel

  • Plugin Flash Player 11.5, per tutti i browser

  • Adobe AIR (versione desktop e mobile)

Ciò significa che la fase di aggiornamento è ancora richiesta nei casi seguenti:

  • Internet Explorer in Windows 8 su processori Intel

  • Flash Player 11.4 e versioni precedenti, tranne che in Google Chrome 22 e versioni successive (tutte le piattaforme) o 21 e versioni successive (Windows)

Nota: potete comunque chiamare senza problemi SystemUpdater.update(SystemUpdaterType.DRM) su un sistema con Flash Player 11.5 o successivo, ma non verrà scaricato nulla.

Il flusso di lavoro di alto livello seguente mostra in che modo un'applicazione può recuperare e riprodurre contenuto protetto. Il flusso di lavoro presuppone che l'applicazione sia progettata specificatamente per riprodurre contenuto protetto da Adobe Access:

  1. Recuperare i metadati del contenuto.

  2. Gestire gli aggiornamenti a Flash Player, se necessario.

  3. Verificare se una licenza è disponibile localmente. In tal caso, caricarla e andare al passaggio 7. In caso contrario, andare al passaggio 4.

  4. Verificare se è richiesta l'autenticazione. In caso contrario, è possibile andare al passaggio 7.

  5. Se l'autenticazione è obbligatoria, recuperare le credenziali di autenticazione dall'utente e passarle al server delle licenze.

  6. Se è richiesta la registrazione a un dominio, iscriversi (AIR 3.0 e successivi).

  7. Dopo aver completato l'autenticazione, scaricare la licenza dal server.

  8. Riprodurre il contenuto.

Qualora non si sia verificato alcun errore e l'utente sia stato autorizzato a visualizzare il contenuto, l'oggetto NetStream invia un oggetto DRMStatusEvent e l'applicazione inizia la riproduzione. L'oggetto DRMStatusEvent contiene le informazioni del voucher correlate che identificano i criteri e le autorizzazioni dell'utente. Ad esempio, contiene informazioni riguardo la possibilità di rendere il contenuto disponibile offline o relative alla data di scadenza della licenza. L'applicazione può utilizzare questi dati per informare l'utente sullo stato dei criteri. Ad esempio, l'applicazione può visualizzare in una barra di stato il numero di giorni rimanenti per cui l'utente può visualizzare il contenuto.

Se all'utente viene concesso l'accesso offline, il voucher viene memorizzato nella cache e il contenuto crittografato viene scaricato nel computer dell'utente e reso accessibile per la durata definita nella cache della licenza. La proprietà detail dell'evento contiene "DRM.voucherObtained" . Il contenuto viene memorizzato localmente in modo automatico affinché possa essere disponibile offline. È inoltre possibile precaricare voucher mediante la classe DRMManager.

Nota: la memorizzazione in cache e il precaricamento dei voucher sono supportati sia in AIR che in Flash Player. Tuttavia, lo scaricamento e l'archiviazione di contenuto crittografato è supportato esclusivamente in AIR.

È responsabilità dell'applicazione gestire esplicitamente tutti gli eventi di errore. Questi eventi includono i casi in cui l'utente immette credenziali valide, ma il voucher di protezione del contenuto crittografato limita l'accesso al contenuto. Ad esempio, un utente autenticato non può accedere al contenuto se i diritti non sono stati pagati. Questo caso si può verificare anche quando due membri registrati dello stesso editore tentano di condividere contenuto che solo uno dei due ha pagato. L'applicazione deve informare l'utente dell'errore e fornire un suggerimento alternativo. Un suggerimento alternativo tipico è fornire istruzioni su come eseguire la registrazione e pagare per i diritti di visualizzazione.

Flusso di lavoro API dettagliato

Questo flusso di lavoro fornisce una visualizzazione più dettagliata del flusso di lavoro con contenuto protetto e descrive le API specifiche utilizzate per riprodurre contenuto protetto da Adobe Access.

  1. Utilizzando l'oggetto URLLoader, caricate i byte del file di metadati del contenuto protetto. Impostate questo oggetto su una variabile, ad esempio metadata_bytes .

    Tutto il contenuto controllato da Adobe Access dispone di metadati Adobe Access. Quando viene creato un pacchetto del contenuto, questi metadati possono essere salvati come un file di metadati separato (.metadata) insieme al contenuto. Per ulteriori informazioni, vedete la documentazione di Adobe Access.

  2. Create un'istanza DRMContentData. Inserite questo codice in un blocco try-catch:

    new DRMContentData( metadata_bytes )

    in cui metadata_bytes è l'oggetto URLLoader ottenuto nel passaggio 1.

  3. (Solo Flash Player) Il runtime verifica la presenza del modulo Adobe Access. Se rilevato, viene generato un IllegalOperationError con codice errore DRMErrorEvent 3344 o DRMErrorEvent 3343.

    Per gestire questo errore, scaricare il modulo Adobe Access utilizzando l'API SystemUpdater. Dopo aver scaricato questo modulo, l'oggetto SystemUpdater invia un evento COMPLETE. Includete un listener di eventi per questo evento che riporta al passaggio 2 quando questo evento viene inviato. Il codice seguente dimostra questi passaggi:

    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); 
    } 

    Se il lettore stesso deve essere aggiornato, viene inviato un evento di stato. Per ulteriori informazioni sulla gestione di questo evento, vedete Intercettazione di un evento di aggiornamento .

    Nota: nelle applicazioni AIR, il programma di installazione di AIR gestisce l'aggiornamento del modulo Adobe Access e gli aggiornamenti del runtime richiesti.
  4. Create dei listener per intercettare eventi DRMStatusEvent e DRMErrorEvent inviati dall'oggetto DRMManager:

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

    Nel listener DRMStatusEvent, verificate che il voucher sia valido (diverso da null). Nel listener DRMErrorEvent, gestite DRMErrorEvents. Vedete Uso della classe DRMStatusEvent e Uso della classe DRMErrorEvent .

  5. Caricate il voucher (licenza) richiesto per la riproduzione del contenuto.

    Provate, innanzitutto, a caricare una licenza memorizzata localmente per riprodurre il contenuto:

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.LOCAL_ONLY)

    Al termine del caricamento, l'oggetto DRMManager invia l'evento DRMStatusEvent.DRM_Status .

  6. Se l'oggetto DRMVoucher non è null, il voucher è valido. Ignorate il passaggio 13.

  7. Se l'oggetto DRMVoucher è null, verificate il metodo di autenticazione richiesto dal criterio per questo contenuto. Utilizzate la proprietà DRMContentData.authenticationMethod .

  8. Se il metodo di autenticazione è ANONYMOUS , andate al passaggio 13.

  9. Se il metodo di autenticazione è USERNAME_AND_PASSWORD , l'applicazione deve fornire un meccanismo per consentire all'utente di immettere credenziali. Passate queste credenziali al server delle licenze per autenticare l'utente:

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

    DRMManager invia un evento DRMAuthenticationErrorEvent se l'autenticazione non riesce o un evento DRMAuthenticationCompleteEvent se l'autenticazione riesce. Create listener per questi eventi.

  10. Se il metodo di autenticazione è UNKNOWN , è necessario utilizzare un metodo di autenticazione personalizzato. In questo caso, il fornitore di contenuto ha fatto in modo che l'autenticazione avvenga fuori banda, senza utilizzare le API di ActionScript 3.0. La procedura di autenticazione personalizzata deve produrre un token di autenticazione che possa essere trasmesso al metodo DRMManager.setAuthenticationToken() .

  11. Se l'autenticazione non riesce, l'applicazione deve tornare al passaggio 9. Assicuratevi che l'applicazione disponga di un meccanismo per gestire e limitare errori di autenticazione ripetuti. Ad esempio, dopo tre tentativi, viene visualizzato un messaggio all'utente in cui si indica che l'autenticazione non è riuscita e che il contenuto non può essere riprodotto.

  12. Per utilizzare il token memorizzato anziché richiedere all'utente di immettere le credenziali, impostate il token con il metodo DRMManager.setAuthenticationToken() . Scaricate quindi la licenza dal server delle licenze e riproducete il contenuto come nel passaggio 8.

  13. (facoltativo) Se l'autenticazione riesce, potete acquisire il token di autenticazione, che è un array di byte memorizzati nella cache. Recuperate questo token con la proprietà DRMAuthenticationCompleteEvent.token . Potete memorizzare e utilizzare il token di autenticazione in modo che l'utente non sia costretto a immettere ripetutamente credenziali per questo contenuto. Il server delle licenze determina il periodo di validità del token di autenticazione.

  14. Se l'autenticazione riesce, scaricate la licenza dal server delle licenze.

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.FORCE_REFRESH)

    Al termine del caricamento, l'oggetto DRMManager invia l'evento DRMStatusEvent.DRM_STATUS. Intercettate questo evento e quando viene inviato potete riprodurre il contenuto.

  15. Riproducete il video creando un oggetto NetStream e chiamando il suo metodo 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 e oggetti sessione

Se l'oggetto DRMContentData viene creato, esso viene utilizzato come oggetto di sessione che fa riferimento al modulo Flash Player DRM. Tutte le API DRMManager che ricevono l'oggetto DRMContentData andranno a utilizzare quel particolare modulo DRM. Tuttavia, vi sono due API di DRMManager che non utilizzano DRMContentData . Esse sono:
  1. authenticate()

  2. setAuthenticationToken()

Poiché non vi è alcun oggetto DRMContentData associato, se si effettuano chiamate a queste API di DRMManager , verrà utilizzato il modulo DRM più recente del disco. Ciò potrebbe risultare problematico se viene eseguito un aggiornamento del modulo DRM durante un flusso di lavoro DRM dell'applicazione. Si consideri lo scenario seguente:
  1. L'applicazione crea contentData1 per un oggetto DRMContentData che impiega AdobeCP1 come modulo DRM.

  2. L'applicazione effettua una chiamata al metodo DRMManager.authenticate(contentData1.serverURL,...) .

  3. L'applicazione effettua una chiamata al metodo DRMManager.loadVoucher(contentData1, ...) .

Se viene eseguito un aggiornamento al modulo DRM prima che l'applicazione concluda il punto 2, il metodo DRMManager.authenticate() finirà con l'autenticarsi utilizzando AdobeCP2 come modulo DRM. Il metodo loadVoucher() al punto 3 non avrà esito positivo, in quanto utilizza ancora AdobeCP1 come modulo DRM. L'aggiornamento può avvenire a causa di un'altra applicazione che effettua una chiamata all'aggiornamento del modulo DRM. Per evitare il problema, potete chiamare l'aggiornamento del modulo DRM all'avvio dell'applicazione.

Eventi correlati a DRM

Il runtime invia numerosi eventi quando un'applicazione tenta di riprodurre contenuto protetto:

  • DRMDeviceGroupErrorEvent (solo AIR) inviato da DRMManager

  • DRMAuthenticateEvent (solo AIR), inviato da NetStream

  • DRMAuthenticationCompleteEvent, inviato da DRMManager

  • DRMAuthenticationErrorEvent, inviato da DRMManager

  • DRMErrorEvent, inviato da NetStream e DRMManager

  • DRMStatusEvent, inviato da NetStream e DRMManager

  • StatusEvent

  • NetStatusEvent. Vedete Intercettazione di un evento di aggiornamento

Per supportare contenuto protetto da Adobe Access, aggiungete listener di eventi per la gestione di eventi DRM.

Precaricamento di voucher per la riproduzione non in linea

Potete precaricare i voucher (licenze) richiesti per riprodurre contenuto protetto da Adobe Access. I voucher precaricati consentono agli utenti di visualizzare il contenuto, con o senza una connessione Internet attiva. (Il processo stesso di precaricamento richiede una connessione Internet). Potete utilizzare il metodo preloadEmbeddedMetadata() della classe NetStream e la classe DRMManager per precaricare i voucher. In AIR 2.0 e versioni successive, potete utilizzare un oggetto DRMContentData per precaricare i voucher direttamente. Questa tecnica è preferibile poiché consente di aggiornare l'oggetto DRMContentData in maniera indipendente dal contenuto. (Il metodo preloadEmbeddedData() recupera DRMContentData dal contenuto.)

Uso di DRMContentData

I passaggi seguenti descrivono il flusso di lavoro di precaricamento del voucher per un file multimediale protetto mediante un oggetto DRMContentData.

  1. Recuperate i metadati binari per il contenuto inserito in un pacchetto. Se utilizzate Java Reference Packager di Adobe Access, questo file di metadati viene automaticamente generato con un'estensione .metadata . Potete, ad esempio, scaricare questi metadati utilizzando la classe URLLoader.

  2. Create un oggetto DRMContentData, passando i metadati alla funzione di costruzione:

    var drmData:DRMContentData = new DRMContentData( metadata );
  3. I passaggi rimanenti sono identici al flusso di lavoro descritto in Nozioni fondamentali sul flusso di contenuto protetto .

Uso di preloadEmbeddedMetadata()

Di seguito viene descritto il flusso di lavoro per precaricare il voucher per un file multimediale protetto da DRM utilizzando preloadEmbeddedMetadata() .

  1. Scaricate e archiviate il file multimediale. (I metadati DRM possono essere precaricati solo da file archiviati localmente.)

  2. Create gli oggetti NetConnection e NetStream, fornendo le implementazioni per le funzioni di callback onDRMContentData() e onPlayStatus() dell'oggetto client NetStream.

  3. Create un oggetto NetStreamPlayOptions e impostate la proprietà stream sull'URL del file multimediale locale.

  4. Chiamate il metodo preloadEmbeddedMetadata() della classe NetStream, passando l'oggetto NetStreamPlayOptions che identifica il file multimediale da analizzare.

  5. Se il file multimediale contiene metadati DRM, viene richiamata la funzione di callback onDRMContentData() . I metadati vengono passati a questa funzione come un oggetto DRMContentData.

  6. Utilizzate l'oggetto DRMContentData per ottenere il voucher, utilizzando il metodo loadVoucher() della classe DRMManager.

    Se il valore della proprietà authenticationMethod dell'oggetto DRMContentData è flash.net.drm.AuthenticationMethod.USERNAME_AND_PASSWORD , autenticate l'utente sul server di gestione dei diritti multimediali prima di caricare il voucher. Le proprietà serverURL e domain dell'oggetto DRMContentData possono essere passate al metodo DRMManager authenticate() della classe DRMManager insieme alle credenziali dell'utente.

  7. La funzione di callback onPlayStatus() viene richiamata al termine dell'analisi del file. Se la funzione onDRMContentData() non è stata chiamata, il file non contiene i metadati richiesti per ottenere un voucher. La chiamata mancante può anche significare che Adobe Access non protegge questo file.

L'esempio di codice per AIR riportato di seguito illustra come precaricare un voucher per un file multimediale locale:

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(); 
    } 
} 
}