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

问题

最近将一个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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值