此文章由人工翻译。 将光标移到文章的句子上,以查看原文。
|
译文
原文
|
在将数字版权管理 (DRM) 集成到 Silverlight 应用程序后,您可以针对各种方案更好地保护内容并更安全地跨平台交付内容,包括流处理内容、渐进式下载内容、租赁内容和订阅。
说明: |
---|
本主题特定于 Silverlight 4 和 Silverlight 5 Beta。 Digital Rights Management (Silverlight 3)." >若要了解 Silverlight 3 中的 DRM,请参见数字版权管理 (Silverlight 3)。 |
本主题包括下列各节。
可以使用 DRM 来帮助您交付音频和视频内容,这样更安全且更好地保护内容不受未经授权的获取和再分发。 这种保护机制可以集成到各种业务方案中,包括:
联机方案:这些方案要求用户在播放媒体内容时处于联机状态:
实时流处理:实时流处理也称为“真正的流处理”,它直接将内容发送到计算机或设备,而不将文件保存到硬盘。 仅当广播时,实时流才可用。 实时流处理的示例是 Internet 电视和广播。
渐进式下载:渐进式下载使得用户能够在媒体正处于下载时进行播放。 从用户的角度来看,渐进式下载与实时流处理之间的主要区别在于:渐进式下载的内容存储在用户的计算机或设备上(至少是临时存储)。
脱机方案:这些方案允许用户在播放内容时处于脱机状态。 这些方案的确要求在用户的计算机或设备上安装脱机版 Silverlight 运行时,并且确实要求用户处于联机状态(至少应间歇性联机),以便最初下载内容并重续订阅。
脱机下载文件(一次性购买):用户从 Internet 下载内容,然后使用脱机版 Silverlight 播放器播放内容。 例如,一个联机视频商店向客户收取费用让其下载视频文件,用户可以在需要时在脱机版 Silverlight 播放器中播放此文件。 Domains later in this article)." >DRM 软件可以将视频文件的再分发限制为一台或更多台设备(请看本文后面的域)。
租赁:您可以在 DRM 许可证中指定时间限制,以限制内容的播放。 例如,某个联机视频商店可能提供其视频用于出租。 一旦购买了租赁内容并下载了许可证,许可证就会在许可证签发之日起的 30 天之后或首次播放的 24 小时之后过期(以先到者为准)。
订阅:使客户能够根据订阅模型播放内容。 例如,联机视频商店的客户支付每月费用,可联机观看最多 100 个小时的电视内容和下载最多 20 集电视剧。 为了续订其订阅,客户需要支付每月费用,并每月至少需要连接到此服务一次,因为订阅许可证每 45 天就会过期。
以下各节说明如何启用联机 Silverlight DRM 方案。 Silverlight DRM Offline Scenarios." >此处介绍的许多概念也适用于脱机方案;但脱机方案(如租赁和订阅)将在稍后的 Silverlight DRM 脱机方案中介绍。
本节考察在 Silverlight 中播放 DRM 内容所需的最低限度的组件。 这些组件同时适用于联机方案和脱机方案;但是,某些方案要求提供附加组件,后续章节中将介绍它们。
下图汇总了 Silverlight 联机播放 DRM 内容所需的过程以及推动这些过程顺利完成所需的客户端/服务器交互。 之后将更详细地讨论其中的每个步骤。
说明: |
---|
如果试图播放内容的计算机已具有许可证,则可能不需要再次执行许可证获取过程;使用现有的许可证可能就可以进行播放。 |
用户尝试在 Silverlight 应用程序中播放某些存储在分发服务器上的受 DRM 保护的内容(分发服务器通常为 Web 服务器,用来分发您的内容)。 Silverlight 客户端下载内容(如果是流,则为部分内容)和标头。
在 Silverlight 请求许可证来解密内容之前,Silverlight 必须先确定用户的计算机上是否安装了适当的 DRM 软件。 这种软件称为个性化黑盒 (IBX),是在播放任何受保护的内容之前所需的 DRM 客户端组件。 个性化组件软件使客户端计算机可以请求和使用 DRM 许可证。 它还帮助保护在解密过程中用到的敏感数据。
如果客户端上还没有适当的个性化组件软件,客户端将自动向 Microsoft Individualization Service 请求该组件。 获取个性化的组件软件的过程称为“个性化”。 Silverlight 通过向 Microsoft Individualization Service 发送消息来个性化用户的计算机。 用户可以阻止发送此信息。 Error Handling later in this topic." >有关更多信息,请参见本主题后面的错误处理。
在安装了有效的个性化组件之后,客户端通常不需要再次进行个性化处理。 一种例外情况是 PlayReady 许可证服务器 SDK(由第三方运行)拒绝向给定的 IBX 版本签发许可证。 如果发生拒绝情况,则客户端将自动启动更新。
您可以使用 MediaElement.CurrentState 属性检测在某台计算机上何时首次发生个性化。 Detecting DRM State." >有关更多信息,请参见检测 DRM 状态。
当客户端上存在有效的个性化组件软件时,就可以开始播放 DRM 了。 当用户首次开始播放受保护的内容时,Silverlight 客户端将联系 PlayReady 许可证服务器以获取许可证(许可证服务器由您或您的服务提供商控制)。 如果许可证服务器批准该请求,则颁发许可证,客户端将使用该许可证来解密特定的媒体文件。 之后,就可以播放内容了。
管理计算机,使用户可以在上面播放受 DRM 保护的内容,称为"域管理"。管理域是可选的,但在此提到它是因为其在联机和脱机的情况都是很有用的。 Microsoft PlayReady 域特性提供的这一功能对于最终用户体验而言很直观:服务提供商允许用户将一组计算机指定为一个域。
如果计算机对于内容具有域绑定的许可证,则域中的任何计算机都可以使用域中任何其他计算机获取的、受 Microsoft PlayReady 保护的内容。 用户可以轻松地在域中添加或删除计算机,只要域中的计算机总数不超过此服务定义的限制即可。 域管理可通过您所提供的 PlayReady 域服务器(域控制器服务器)来帮助完成。 domains later in this article." >有关更多信息,请参见本文后面的域。
在 Silverlight 4 版本中添加了存储许可证的功能。 许可证服务器可以确定是签发“一次性”许可证还是在客户端上持续有效的许可证。 在客户端上持续有效的许可证存储在一个在个性化期间于客户端上创建的持久性许可证存储区中。 在用户的客户端上存储许可证对于脱机方案尤其有用。 Silverlight DRM Offline Scenarios." >有关更多信息,请参见 Silverlight DRM 脱机方案。
如果用于播放内容的许可证有效,则开始播放。
Silverlight 客户端可以使用两种形式的受 DRM 保护的内容:传统的 Windows Media 数字权限管理 10 (WMDRM 10) 和较新的 PlayReady。 这 种灵活性使得使用 WMDRM 10 SDK 加密的现有内容可以同时在 Silverlight 和其他支持 DRM 的 Windows Media 播放软件(如 Windows Media Player)中播放,并使得仅限在 Silverlight 中播放的媒体可提供更高程度的内容保护。
说明: |
---|
WMDRM 与 PlayReady 使用不同的许可证。 例如,如果您希望用户同时在 Windows Media Player 或 Silverlight 播放器中播放给定的受 DRM 保护的视频,则需要两个许可证,每种播放方式对应于一个许可证。 |
说明: |
---|
PlayReady 并不仅仅用在 Silverlight 中。 PlayReady Whitepaper." >有关 PlayReady 的更多信息,请参见 PlayReady 白皮书。 |
说明: |
---|
尽管 Silverlight 可以播放 PlayReady 和 WMDRM 打包的内容,但不支持这些技术的整个生态系统。 此外,为了在 Silverlight 中播放 WMDRM 打包的内容,您需要 PlayReady 服务器(请参见上面的关系图)。 |
即使您只打算使用 WMDRM 加密内容,也要注意您将需要至少一个 PlayReady 许可证服务器才能将许可证分发到 Silverlight 客户端。 同时还要注意,Silverlight DRM 当前仅支持 PlayReady 的部分功能。 下面列出了使用 Silverlight DRM 时的重要限制:
Silverlight 并非支持 PlayReady 所支持的全部文件类型。 Silverlight 只支持播放 DRM 加密的 VC1、WMA、WMA pro、h.264 和 AAC 流。
在设置将 DRM 与 Silverlight 结合起来使用的体系结构时,请谨记一些注意事项:
在对内容进行流处理时,您是从实时源中实时地进行编码和流处理,还是按需对预先加密的文件进行流处理?
您的客户使用 Silverlight 播放内容还是也使用 Windows Media Player?
您有希望用来为 Silverlight 客户提供服务的大型 WMDRM 打包内容库(使用 WMDRM SDK 进行打包)吗?或者您能使用 PlayReady 打包您的全部内容吗?
是否要使用 PIFF 格式? 在使用 PlayReady 时支持 PIFF。
无论这些注意事 项的内容如何,如果您希望向 Silverlight 提供 DRM 内容,都需要购买至少一个 PlayReady 许可证服务器;不过,这些问题的回答会决定您是能够仅使用 PlayReady 打包完成任务,还是还需要在整个 DRM 解决方案中处理 WMDRM 打包的内容。
Streaming Content: If you want to encode streaming content in real-time from live sources using PlayReady, you can use a third party solution." > 流内容:如果您希望使用 PlayReady 实时对来自活动源的流内容进行编码,则可以使用第三方解决方案。 此外,在此方案中可以使用 WMDRM。 Playing WMDRM Content in Silverlight later in this topic for possible solutions for integrating WMDRM with Silverlight." >请参见本主题后面的在 Silverlight 中播放 WMDRM 内容,获取将 WMDRM 与 Silverlight 集成的可能的解决方案。 MediaStreamSource which is used in Silverlight to support adaptive streaming, you must use PlayReady packaged content." >如果您正在使用用于在 Silverlight 中支持自适应流的 MediaStreamSource,则必须使用 PlayReady 打包的内容。
Client Player: If your customers are only using Silverlight to playback DRM, then you can package everything with PlayReady; however, WMDRM encryption is required for customers who are also targeting Windows Media Player clients." > 客户端播放器:如果您的客户只使用 Silverlight 播放 DRM,则您可以使用 PlayReady 打包所有内容;但是,如果某些客户也要使用 Windows Media Player 客户端,则还需要使用 WMDRM 加密。
Your Content Library: Regardless whether you are only playing content in Silverlight, if you do not want to package your content using PlayReady, you need to create a DRM solution that takes into account WMDRM-packaged content." > 您的内容库:无论您是否只在 Silverlight 中播放内容,如果您不希望使用 PlayReady 来打包内容,则需要创建考虑 WMDRM 打包内容的 DRM 解决方案。
说明: |
---|
Silverlight 不支持带有脚本流(脚本流通过隐藏式字幕等流提供文本)的 WMDRM 内容。 如果使用脚本流播放 WMDRM 内容,音频和视频将能正常播放,但脚本流将被忽略。 |
下图从概念上说明了如何将服务于非 Silverlight(旧式 WMDRM)客户端的现有 WMDRM 打包内容库与 Silverlight 客户端一起使用。
Point to DRM Content from a Silverlight Application later in this topic)." > 为了包括该库,您需要在 Silverlight 客户端上包括某些逻辑,以便将许可证请求路由到适当的 PlayReady 许可证服务器(请参见本主题后面的从 Silverlight 应用程序指向 DRM 内容)。
对于流式下载或渐进式下载,需要通过以下步骤来将 DRM 与 Silverlight 相集成:
建立必需的服务器基础结构以提供受 DRM 保护的内容。
MediaElement." > 使用 MediaElement 从 Silverlight 应用程序指向这些受保护的内容。
处理预期错误(例如,当用户不允许 DRM 内容时)。
LicenseAcquirer or DomainAcquirer class to gain custom business logic. " > 如果需要,基于 LicenseAcquirer 或 DomainAcquirer 类创建一个子类以获得自定义业务逻辑。
说明: |
---|
对于 WMDRM 内容,将需要 URL 覆盖以将许可证获取指向正确的 PlayReady 许可证服务器。 原因是 WMDRM 内容极有可能在其 WRMHeader 中不包含 PlayReady 许可证服务器这一事实。 |
在使用 DRM 之前,您必须先打包要保护的内容,并使其可从分发服务器提供给客户端。 可以使用打包软件执行此操作。 有几个可用于打包内容的选项。 下面列出了其中的两个选项:
WMDRM 10 SDK。
PlayReady Server SDK。
PlayReady vs. WMDRM earlier in this topic." > 若要了解关于这些技术以及相关服务器配置的更多信息,请参见本主题前面的 PlayReady 与 WMDRM 的对比。
加密和打包内容时,要指定许可证获取 URL (LAURL)。 您可以在 Silverlight 应用程序中重写此值,然后将许可证质询发送到许可证服务器。 如果您有一个要用来同时为 Silverlight 和 Windows Media Player 客户端提供该内容的 WMDRM 打包内容库,则这一点尤其有用。 Playing WMDRM Content in Silverlight earlier in this article and Point to DRM Content from a Silverlight Application next in this article)." >(请参见本文前面的在 Silverlight 中播放 WMDRM 内容和本文下面的从 Silverlight 应用程序指向 DRM 内容)。
Source property of the MediaElement." > 如果只使用 PlayReady 服务器来加密编码的内容,则可以仅使用 MediaElement 的 Source 属性来指向该内容。
<MediaElement x:Name="myMediaElement" Source="myProtectedVideo.wmv" />
这是因为使用 PlayReady Server SDK 打包的内容在其内容标头中包含授权服务器的 URI 位置。 但是,如果您使用 WMRM SDK 来打包内容,则授权服务器的位置将不会包含在标头中,因此您需要指定此 URI。 LicenseServerUriOverride property to specify the URI for the LicenseAcquirer property of the MediaElement to use to find the license:" >为此,请使用 LicenseServerUriOverride 属性为 MediaElement 的 LicenseAcquirer 属性指定用于查找许可证的 URI:
myMediaElement.LicenseAcquirer.LicenseServerUriOverride = new Uri("http://contoso.com/myLicenseServer.asmx", UriKind.Absolute);
MediaElementState enumeration to detect what state the MediaElement is in, specifically, whether the MediaElement is currently individualizing the Silverlight client or acquiring a license (see Silverlight DRM Online Conceptual Overview earlier in this topic)." > 可以使用 MediaElementState 枚举来检测 MediaElement 所处的状态 – 具体而言,即 MediaElement 当前是正在对 Silverlight 客户端进行个性化处理还是获取许可证(请参见本主题前面的 Silverlight DRM 联机概念性概述)。 MediaElement prepares to play the content." >检测这些状态的一个原因是,您可以为用户提供有关 MediaElement 准备播放内容时所发生的情况的反馈。 TextBlock, as in the following example." >例如,当正在进行个性化时或者正在使用 TextBlock 请求许可证时可以通知用户,如下面的示例所示。
if (myMediaElement.CurrentState == MediaElementState.Individualizing) { myStateTextBlock.text = "Downloading DRM Client"; } else if(myMediaElement.CurrentState == MediaElementState.AcquiringLicense) { myStateTextBlock.text = "Aquiring License"; }
当在 Silverlight 中使用 DRM 时,用户可能会收到许多错误。 开发人员应当预计到这些错误并显示适当的消息,以便用户能够了解到没有按预期的方式进行播放的原因,这一点很重要。
例如,用户可能遇到的一个特定于 DRM 的错误发生在如下情况下:用户已经通过在 Silverlight 的“配置”对话框中取消选中下图所示的复选框来选择禁用 DRM。
Silverlight DRM Online Conceptual Overview earlier in this topic)." > 禁用 DRM 将阻止用户的客户端向 Microsoft Individualization Server 请求个性化处理(请参见本主题前面的 Silverlight DRM 联机概念性概述)。
MediaElement attempts to play DRM content in this scenario, the MediaElement raises a new MediaFailed event with the following error: 6008 DRM_E_INDIVIDUALIZATION_DISALLOWED." > 如果 MediaElement 尝试在这种情况下播放 DRM 内容,则 MediaElement 将引发一个新的 MediaFailed 事件以及如下错误:6008 DRM_E_INDIVIDUALIZATION_DISALLOWED。
您可能希望侦听此错误并在它发生时引发您自己的自定义消息。
下表提供了与 Silverlight DRM 关联的错误的列表。 下面所列的错误号在 6000 以上是连续的。 MediaFailed event of the MediaElement (as listed below), synchronous methods and properties can directly throw an exception and asynchronous methods can return exceptions through their corresponding AsyncCompletedEventArgs." >请注意,除了通过 MediaElement 的 MediaFailed 事件完成的错误处理之外(如下所列),同步方法和属性可能直接引发异常,而异步方法可能通过其对应的 AsyncCompletedEventArgs 返回异常。
错误代码 |
备注 |
---|---|
6000 |
MediaElement failed to play the DRM-protected content." > MediaElement 未能播放受 DRM 保护的内容。 |
6001 |
该个性化组件软件未能下载到用户计算机。 MediaElement is in the IndividualizingMediaElementState." >当 MediaElement 位于 IndividualizingMediaElementState 中时,将发生此错误。 出现此错误的一个可能原因是,Silverlight 客户端无法连接到 Microsoft Individualization Server。 |
6002 |
许可证获取失败。 MediaElement is in the AcquiringLicenseMediaElementState." >当 MediaElement 位于 AcquiringLicenseMediaElementState 中时,将发生此错误。 出现此错误的一个可能原因是,Silverlight 客户端无法连接到许可证服务器。 |
6003 |
未能安装个性化组件软件。 |
6004 |
Silverlight 在客户端上的安装已过期并需要更新。 |
6005 |
处理文件头时失败。 例如,文件头的格式可能不正确。 |
6006 |
在 Silverlight 客户端上处理许可证失败。 MediaElement is in the AcquiringLicense MediaElementState." >当 MediaElement 处于 AcquiringLicense MediaElementState 时,将发生此错误。 |
6007 |
PlayReady 许可证服务器允许服务器开发人员返回一个特定于服务的错误。 例如,服务器可能返回以下错误之一:“您需要付账单了”、“此服务不可用”、“您已用完您的月流量”。从许可证服务器返回的 SOAP 异常有由服务器添加的 CustomData 字段中的额外数据。 您需要在 Silverlight 应用程序中编写应用程序逻辑来解释这一情况。 Add Custom Logic later in this topic)." >这些响应主要在实现自定义许可证获取时使用(请参见本主题后面的添加自定义逻辑)。 |
6008 |
用户在客户端的 Silverlight 配置设置中禁用了 DRM。 |
6009 |
超出了个性化处理的最大尝试次数。 |
6010 |
发生 DRM 协议错误。 |
6011 |
需要 DRM 许可证获取 URL 重写。 |
6012 |
发生 DRM 许可证获取重定向错误。 |
6013 |
用户的 HW 配置发生了很大的更改,而 DRM 状态不再有效。 |
6017 |
AcquireLicenseAsync; however, the stream is in unprotected content." > 用户尝试通过使用流来获取许可证(调用 AcquireLicenseAsync);但是,流处于不受保护的内容中。 |
6021 |
DRM 系统不支持客户端 OS。 |
6023 |
不可访问 IBX 服务。 某些恶意软件/间谍软件将会阻止对 *.microsoft.com 的调用,以确保机器已完全修补并保护。 |
6030 |
许可证包含不支持的许可证保护。 |
6031 |
受保护的视频输出连接的完整性受到危害或丢失。 |
6032 |
受保护的图形连接要求重新协商,但无法重新协商。 |
6033 |
已撤消的高带宽数字内容保护 (HDCP) 设备连接到视频输出。 |
6034 |
图形适配器或驱动程序已被篡改。 |
6035 |
在播放期间添加了新图形连接,因此播放停止。 |
6036 |
图形设备的驱动程序证书无效。 |
6040 |
此域已满,不允许用户向此域添加任何其他客户端。 |
6041 |
客户端不是域成员。 |
6042 |
域帐户标识符是未知的。 |
6208 |
DRM 初始化失败 - 对 Silverlight 进行卸载/重新安装可解决此问题。 |
说明: |
---|
msprdrm_server_redirect_compat:false and msprdrm_server_exception_compat:false to your HTTP Web requests." > 如果您要实现您自己的自定义许可证获取,必须将标头 msprdrm_server_redirect_compat:false 和 msprdrm_server_exception_compat:false 添加到您的 HTTP Web 请求中。 否则,错误和重定向消息将无法正常工作。 请参见添加自定义逻辑一节中的代码示例。 |
说明: |
---|
LicenseAcquirer or DomainAcquirer, an InvalidOperationException is thrown." > 如果您针对同一个 LicenseAcquirer 或 DomainAcquirer 启动多个异步操作,将引发 InvalidOperationException。 |
LicenseAcquirer class is used by the MediaElement to handle acquiring licenses for DRM-encrypted content from the PlayReady License Server." > MediaElement 使用 LicenseAcquirer 类来处理针对 DRM 加密内容从 PlayReady 许可证服务器获取许可证的过程。 LicenseAcquirer class and add custom logic, such as adding your own custom authentication scheme to the license request." >您可以基于 LicenseAcquirer 类创建一个子类并添加自定义逻辑,例如,将您自己的自定义身份验证方案添加到许可证请求。
LicenseAcquirer class (named "ManualLicenseAcquirer") and have a MediaElement use it to acquire the license. " > 下面的示例演示如何重写 LicenseAcquirer 类(名为“ManualLicenseAcquirer”)并让 MediaElement 使用它来获取许可证。
<StackPanel x:Name="LayoutRoot" Background="Gray" Orientation="Vertical"> <MediaElement x:Name="myME" Height="100"/> StackPanel>
public partial class Page : UserControl { public Page() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Page_Loaded); } void Page_Loaded(object sender, RoutedEventArgs e) { // Test a full fledged manual acquirer // Set the LicenseAcquirer of the MediaElement to the custom License Acquirer // defined in this sample. myME.LicenseAcquirer = new ManualLicenseAcquirer(myME.Name); // Set the License URI to proper License Server address. myME.LicenseAcquirer.LicenseServerUriOverride = new Uri("http://contoso.com/myLicenseServer.asmx", UriKind.Absolute); myME.MediaFailed += new EventHandler(myME_MediaFailed); // Set the source of the MediaElement to the URL of the media encrypted with WMDRM. myME.Source = new Uri("http://contoso.com/wmdrm_url.wmv", UriKind.Absolute); } void myME_MediaFailed(object sender, ExceptionRoutedEventArgs e) { string errorMessage = ""; if (e.ErrorException.ToString().Contains(" 6001 ")) { errorMessage = "The individualization component software failed to" + " download to the user’s computer. This error would" + " come up when the MediaElement is in the Individualizing" + " MediaElementState. One possible reason for this error is" + " that the Silverlight client cannot connect the Microsoft" + " Individualization Server."; } else if (e.ErrorException.ToString().Contains(" 6004 ")) { errorMessage = " The installation of Silverlight on the client is" + " out of date and needs to be updated."; } else { errorMessage = "MediaFailed: " + e.ErrorException.Message + "."; } System.Windows.Browser.HtmlPage.Window.Alert(errorMessage); } // makes license request explicitly public class ManualLicenseAcquirer : LicenseAcquirer { private string challengeString; string _mediaElementName; public ManualLicenseAcquirer(string mediaElementName) { _mediaElementName = mediaElementName; } // The default implementation of OnAcquireLicense calls into the MediaElement to acquire a // license. It is called when the Media pipeline is building a topology and will be raised // before MediaOpened is raised. protected override void OnAcquireLicense(System.IO.Stream licenseChallenge, Uri licenseServerUri) { StreamReader sr = new StreamReader(licenseChallenge); challengeString = sr.ReadToEnd(); // Need to resolve the URI for the License Server -- make sure it is correct // and store that correct URI as resolvedLicenseServerUri. Uri resolvedLicenseServerUri; if (LicenseServerUriOverride == null) resolvedLicenseServerUri = licenseServerUri; else resolvedLicenseServerUri = LicenseServerUriOverride; // Make a HttpWebRequest to the License Server. HttpWebRequest request = WebRequest.Create(resolvedLicenseServerUri) as HttpWebRequest; request.Method = "POST"; // Set ContentType through property request.ContentType = "application/xml"; // ADD REQUIRED HEADERS. // The headers below are necessary so that error handling and redirects are handled // properly via the Silverlight client. request.Headers["msprdrm_server_redirect_compat"] = "false"; request.Headers["msprdrm_server_exception_compat"] = "false"; // Initiate getting request stream IAsyncResult asyncResult = request.BeginGetRequestStream(new AsyncCallback(RequestStreamCallback), request); } // This method is called when the asynchronous operation completes. void RequestStreamCallback(IAsyncResult ar) { HttpWebRequest request = ar.AsyncState as HttpWebRequest; // populate request stream request.ContentType = "text/xml"; Stream requestStream = request.EndGetRequestStream(ar); StreamWriter streamWriter = new StreamWriter(requestStream, System.Text.Encoding.UTF8); streamWriter.Write(challengeString); streamWriter.Close(); // Make async call for response request.BeginGetResponse(new AsyncCallback(ResponseCallback), request); } private void ResponseCallback(IAsyncResult ar) { HttpWebRequest request = ar.AsyncState as HttpWebRequest; WebResponse response = request.EndGetResponse(ar); SetLicenseResponse(response.GetResponseStream()); } } }
某些用户目前没有可用的带宽来通过 Internet 观看高质量视频。 他们确实具有高速连接,可用于下载内容供以后观看。 其他用户可能希望先下载电影,供以后在网络不可用时观看,例如,在飞机上或在朋友的家里(没有 Internet 连接)。 能够向脱机内容提供数字版权管理 (DRM),但仍然具有增强的保护功能,这对于启用各种内容发布业务方案(如媒体采购、订阅和租赁等)都是关键所在。
或许最简单的脱机方案是用户购买一段内容,然后将其下载到计算机上,需要时进行播放。
因为用户正在试图脱机播放受保护的内容,所以,许可证验证也需要脱机发生。 Silverlight DRM Online Conceptual Overview earlier in this article)." >为此,已下载内容需要的许可证存储在称为持久性许可证存储区的位置,此存储区是在初始化期间在用户的计算机上创建的(请参阅本文前面的 Silverlight DRM 联机概略性概述)。 当用户试图播放脱机内容时,内容将通过在持久性许可证存储区中查找其对应的许可证尝试验证播放。 Enumerating through Licenses." >您可以在枚举许可证一节中了解有关枚举这些许可证的更多信息。
在脱机方案中,用户下载内容文件,然后播放它。 由于下载媒体文件可能要花时间和带宽,因此,请考虑在允许下载之前验证用户的许可证,而不是在用户尝试播放时进行验证。 下面的示例演示如何执行此操作。
下面的应用程序使用一个密钥标识符和一个身份验证标记将许可证获取请求发送到许可证服务器。 许可证服务器将响应一个许可证以及从中下载内容的 URL。
// Called when the user is online and wants to download some protected content. public void GetLicensePreDelivery(string customData, Guid keyId) { Uri licenseServerUrl = new Uri("http://contoso.com/myLicenseServer.asmx"); LicenseAcquirer acquirer = new LicenseAcquirer(); acquirer.ChallengeCustomData = customData; // Set the License URI to proper License Server address. acquirer.LicenseServerUriOverride = licenseServerUrl; acquirer.AcquireLicenseCompleted += new EventHandler(acquirer_Completed); acquirer.AcquireLicenseAsync(keyId, ContentKeyType.Aes128Bit, Guid.Empty); }
AcquireLicenseAsync call completes after starting the license acquisition but without waiting for the long content download operation to finish." > AcquireLicenseAsync 调用在启动许可证获取之后完成,而无需等待长时间的内容下载操作完成。 AcquireLicenseCompleted event is called." >当许可证获取确实完成后,将调用在 AcquireLicenseCompleted 事件上配置的委托。 acquirer_Completed method, and it might look something like in the following example." >在此示例中,这是 acquirer_Completed 方法,它可能类似下面示例中的内容。
public void acquirer_Completed(object sender, AcquireLicenseCompletedEventArgs e) { if (e.Error != null) { // take appropriate action. Might be retrying for instance. } else if (e.Cancelled) { // take appropriate action. Might be nothing. } else { // // We acquired the license successfully, go ahead and download // the content. Note the service decided to stash the content // url in the LicenseAcquirer response custom data. // string contentAcquisitionUrl = e.ResponseCustomData; DownloadContent(contentAcquisitionUrl); } }