首页 > Silverlight > 跨域下请求Silverlight Xap包引起的问题

跨域下请求Silverlight Xap包引起的问题

Silverlight ,

问题

最近将一个Silverlight应用从一个域挪到另外一个域下之后,出了一些莫名其妙的问题。在加载完Silverlight之后,整个Silverlight UI一闪就消失了。左下角没有异常信息,异常报错的窗口——系统会捕获到所有异常,将其使用Alert方法展示给用户——也没有弹出来。

后来使用HTTP Watch观察了一下,发现在调用web service的时候服务端返回了错误(服务端会将异常封装成一个自定义的数据结构返回给客户端)。奇怪的是,既然返回了错误,按理应该会弹出窗口显示错误信息才是,但是却什么信息也没弹出来,整个UI界面一闪就消失了。

查了很久之后终于找到相关的资料,原来Silverlight和宿主(承载Silverlight应用的网页)Dom元素和脚本的交互在跨域下也有一些限制。

Silverlight HTML桥的安全设置

在Silverlight2中,有三个参数控制着Silverlight和HTML的交互行为。

  • enableHtmlAccess —— Silverlight插件属性,禁止恶意的基于 Silverlight 的跨域应用程序访问主页面的 JavaScript 和 DOM 代码。
  • ExternalCallersFromCrossDomain —— 部署清单属性,禁止恶意的跨域宿主访问由基于 Silverlight 的应用程序公开的可编写脚本的属性、方法或事件。
  • AllowHtmlPopupwindow —— Silverlight插件属性,控制基于 Silverlight 的跨域应用程序打开的弹出窗口。在此属性设置为 false 时(在从包含页或承载 iframe 以外的其他域加载 Silverlight 控件时的默认值),开发人员无法调用 [HtmlPage.PopupWindow]。

enableHtmlAccess

这个属性是在Silverlight插件中配置的。它使到Xap包中的托管代码可以访问宿主页面中的DOM元素以及Javascript代码。此插件一旦初始化之后就是只读的。在同域情况下,此属性默认值为true,而在跨域情况下(宿主和Xap包不在同个域下)默认值为false。这也就是为什么我们一般情况下不需要设置此参数的缘故。

<div id="silverlightControlHost">
    <object data="data:application/x-silverlight," type="application/x-silverlight-2" width="300" height="100">
        <param name="source" value="http://www.domain1.com/silverlightapp.xap"/>
        <param name="enableHtmlAccess" value="true" />
    </object>
</div>

将此属性设置为true之后才可以访问以下对象:

这也就解释了文章开头提到的问题。

因为在出问题的Silverlight应用中,会捕获所有的异常,并将异常描述信息通过HtmlWindow.Alert方法展示给用户。而Alert的实现应该也是通过调用Javascript的alert函数来完成的,因此在跨域情况下,如果直接调用跨域宿主的Javascript代码是会抛出异常的。不过对于此异常Silverlight的处理行为还是很糟糕的。

    如果出于某种目的需要禁用此属性,防止Silverlight意外篡改宿主Dom元素,或者限制Silverlight可访问的Dom元素,那么可以采用以下步骤实现:
    3. Javascript调用此对象接口,将所需要的Dom元素传给Silverlight托管代码
    需要注意的是,这种方式是由Javascript发起的操作,需要配置ExternalCallersFromCrossDomain属性为true。

ExternalCallersFromCrossDomain

ExternalCallersFromCrossDomain属性是在部署清单appmanifest.xaml中配置的。它是用来限制跨域情况下脚本对Silverlight托管代码的访问的,在同域情况下此属性无效。配置示例如下:

<Deployment xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    EntryPointAssembly="MyAppAssembly"
    EntryPointType="MyNamespace.MyApplication"
    ExternalCallersFromCrossDomain="ScriptableOnly"
>
<Deployment.Parts>
    <AssemblyPart Source="MyAppAssembly.dll” />
    <AssemblyPart Source="MyUserControl.dll" />
  </Deployment.Parts>
</Deployment>

此属性有两个取值,ScriptableOnly和NoAccess(beta2的FullAccess取值在正式版的时候已经废弃了)。当设置为ScriptableOnly时,Javascript可以访问Silverlight托管代码显式注册的脚本入口,而不能查询或设置其他对象的属性。另外,它也不接受事件通知。如果设置为NoAccess,那么Javascript无法访问托管代码里的任何对象接口。

 

关于这两个属性的详细信息,参见SilverlightHTML 桥中的安全设置

——Kevin Yang

本博客遵循CC协议2.5,即署名-非商业性使用-相同方式共享
写作很辛苦,转载请注明作者以及原文链接~
如果你喜欢我的文章,你可以订阅我的博客:-D点击订阅我的文章

  1. X﹏X 到现在还没有评论~
  1. 暂时没有trackbacks.