繁体   English   中英

通过HostScript在XBAP中访问部分信任的JavaScript对象:回调中的SecurityException

[英]Partial Trust JavaScript Object Access in XBAP via HostScript: SecurityException in Callbacks

我在WPF 4中遇到了XBAP脚本互操作功能的问题,它涉及以下各项的组合:

  1. 从.NET访问脚本对象的成员
  2. 在从JavaScript调用的回调中运行.NET代码
  3. 以部分信任运行

这似乎是“任意选择两个”方案...如果我尝试完成所有这三个操作,则会收到SecurityException

例如,将1和3组合起来很容易。 我可以将其放入托管网页的脚本中:

function ReturnSomething()
{
    return { Foo: "Hello", Bar: 42 };
}

然后,在我的WPF代码后面的按钮单击处理程序中,我可以这样做:

dynamic script = BrowserInteropHelper.HostScript;
if (script != null)
{
    dynamic result = script.ReturnSomething();
    string foo = result.Foo;
    int bar = result.Bar;
    // go on to do something useful with foo and bar...
}

即使在部分信任部署中,也可以正常工作。 (我正在使用Visual Studio 2010中WPF浏览器应用程序模板提供的默认ClickOnce安全设置,该模板将调试XBAP好像它在Internet区域中一样运行。)到目前为止,一切都很好。

我还可以结合使用2和3。要使我的.NET方法可从JavaScript调用,可悲的是,我们不能只传递一个委托,我们必须这样做:

[ComVisible(true)]
public class CallbackClass
{
    public string MyMethod(int arg)
    {
        return "Value: " + arg;
    }
}

然后我可以声明一个如下所示的JavaScript方法:

function CallMethod(obj)
{
    var result = obj.MyMethod(42);
    var myElement = document.getElementById("myElement");
    myElement.innerText = "Result: " + result;
}

现在,在WPF按钮单击处理程序中,我可以执行以下操作:

script.CallMethod(new CallbackClass());

因此,我的WPF代码(通过BrowserInteropHelper.HostScript )调用了我的JavaScript CallMethod函数,该函数又回调了.NET代码-具体而言,它调用了CallbackClass公开的MyMethod方法。 (或者我可以将回调方法标记为具有[DispId(0)]属性的默认方法,这将使我简化JavaScript代码-脚本可以将参数本身视为方法。这两种方法均会产生相同的结果。)

MyMethod回调已成功调用。 我可以在调试器中看到从JavaScript(42)传递的参数正确通过了(已正确地强制转换为int)。 当我的方法返回时,由于剩下的CallMethod函数,它返回的字符串最终出现在HTML UI中。

太好了,所以我们可以做2和3。

但是,将这三个结合在一起怎么办? 我想修改回调类,以便它可以与脚本对象一起使用,就像我的第一个代码片段ReturnSomething函数所返回的ReturnSomething 我们知道完全有可能使用此类对象,因为第一个示例成功了。 所以您认为我可以这样做:

[ComVisible(true)]
public class CallbackClass
{
    public string MyMethod(dynamic arg)
    {
        return "Foo: " + arg.Foo + ", Bar: " + arg.Bar;
    }
}

然后将我的JavaScript修改如下:

function CallMethod(obj)
{
    var result = obj.MyMethod({ Foo: "Hello", Bar: 42 });
    var myElement = document.getElementById("myElement");
    myElement.innerText = "Result: " + result;
}

然后像以前一样从我的WPF按钮单击处理程序中调用该方法:

script.CallMethod(new CallbackClass());

这成功调用了JavaScript CallMethod函数,该函数成功回调了MyMethod C#方法,但是当该方法尝试检索arg.Foo属性时,我收到了SecurityException以及一条RequestFailed消息。 这是调用堆栈:

at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessSecurityEngine.Check(PermissionSet permSet, StackCrawlMark& stackMark)
at System.Security.PermissionSet.Demand()
at System.Dynamic.ComBinder.TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject& result, Boolean delayInvocation)
at Microsoft.CSharp.RuntimeBinder.CSharpGetMemberBinder.FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
at System.Dynamic.DynamicMetaObject.BindGetMember(GetMemberBinder binder)
at System.Dynamic.GetMemberBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args)
at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at XBapDemo.CallbackClass.MyMethod(Object arg)

这是该异常报告的整个跟踪。 CallbackClass.MyMethod之上,Visual Studio显示了两个[从本地到托管过渡]和[AppDomain过渡]-这就是整个堆栈。 (显然,我们现在处于不同的线程上。此回调发生在“线程”面板上描述为工作线程的状态-我可以看到主线程仍位于我的WPF按钮单击处理程序内,等待对JavaScript的调用CallMethod函数返回。)

显然,问题在于DLR最终将JavaScript对象包装在需要完全信任的ComBinder中。 但是在较早的情况下,我通过HostScript调用JavaScript方法并返回了一个对象, HostScript为我将HostScript包装在System.Windows.Interop.DynamicScriptObject中。

DynamicScriptObject类特定于WPF XBAP脚本互操作-它不是常见DLR类型的一部分,并且在PresentationFramework.dll定义。 据我所知,它的工作之一就是使C#的dynamic关键字可以访问JavaScript属性而无需完全信任,即使这些属性是通过COM互操作(通常需要完全信任)访问的,封面。

据我所知,问题在于,对于从其他DynamicScriptObject实例(例如HostScript )返回的对象,只能获得这些DynamicScriptObject包装器。 使用回调,似乎不会发生这种包装。 在我的回调中,我得到了一种动态包装程序C#,通常在普通的旧的COM互操作方案中,这种动态包装程序会给我这种情况,此时,它要求我完全信任。

以完全信任的方式运行它可以正常工作-这就是上面列表中的“ 1和2”组合。 但是我不想完全信任。 (我想要1、2 3。)在回调情况之外,我可以很好地访问JavaScript对象成员。 似乎大多数时候我都可以访问JavaScript对象,但似乎是不一致的,但是禁止在回调中访问相同的对象。

有没有解决的办法? 或者,如果我想在回调中做任何有趣的事情,我注定要完全信任我的代码吗?

我已经有一段时间没有做过XBAP了,但是我很好奇它是否是导致问题的动态类型。 尝试将动态参数更改为type object,然后查看它是否可以工作。

[ComVisible(true)] 
public class CallbackClass 
{     
    public string MyMethod(object arg)     
    {         
          return "Arg is: " + arg.ToString();  
    } 
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM