WPF部分信任安全

    一般来说,Internet 应用程序应该被限制直接访问重要系统资源的能力,以防止恶意的破坏。默认设置下,HTML 和客户端脚本语言都不能够访问关键的系统资源。 因为 Windows Presentation Foundation(WPF) 浏览器宿主应用程序可以从浏览器启动,它们也应遵循一组相似的限制。为了实施这些限制,WPF 同时依赖代码访问安全性 (CAS:Code Access Security) 和 ClickOnce (请参阅 Windows Presentation Foundation Security Strategy - Platform Security)。 默认设置下,浏览器宿主应用程序总是请求 ”Internet 区域“ CAS 组的权限,而不管它们是从 Internet、 本地 Intranet 或本地计算机启动的。 以任何小于完整权限集的权限运行的应用程序都被称为运行在部分信任安全环境中的应用程序。

    WPF 提供了多种支持以确保尽可能多的功能能够安全的用于部分信任环境,并且与CAS一道为部分信任环境编程提供了额外的支持。

    本主题包含以下各节:


    部分信任环境下支持的WPF特性

        下表列出了可以在Internet 区域权限集的限制下安全使用的WPF高级特性。

    表 1:在部分信任环境下可以安全使用的 WPF 功能

    功能区域 功能

    常规

    浏览器窗口

    源站点访问

    IsolatedStorage(隔离存储:512KB 限制)

    UIAutomation 提供程序

    命令

    输入法 (IME)

    Tablet Stylus and Ink

    使用鼠标捕获和移动事件的模拟拖 / 放

    OpenFileDialog

    XAML 反序列化 (通过 XamlReader.Load)

    Web 集成

    浏览器下载对话框

    用户启动的顶级导航

    mailto:links

    统一资源标识符参数

    HTTPWebRequest

    内嵌于IFRAME的WPF 内容

    承载相同站点的 HTML 页

    Web Services(ASMX)

    视觉效果

    2D和3D

    动画

    媒体 (源站点和跨域)

    图像 / 音频 / 视频

    图像编码

    阅读

    FlowDocuments

    XPS 文档

    嵌入式及系统字体

    CFF和TrueType 字体

    编辑

    拼写检查

    RichTextBox

    纯文本和Ink剪贴板支持

    用户启动的粘贴

    复制选定的内容

    控件

    常用控件

        此表粗略概括了 WPF 功能, 有关更多详细信息请参见SDK文档,其中描述了WPF中每项功能所需要的权限。在部分信任环境中,以下WPF功能有特殊的注意事项:


        下表概括了在Internet 区域权限集限制内不能安全运行的 WPF 功能。

    表 2:在部分信任环境中不安全的WPF 功能

    功能区域 功能

    常规

    窗口 (应用程序定义的窗口和对话框)

    SaveFileDialog

    文件系统

    注册表访问

    拖/放

    XAML 序列化 (通过 XamlWriter.Save)

    UIAutomation 客户端

    源窗口访问 (HwndHost)

    完全语音支持

    Windows Forms 互操作性

    Web 集成

    Web Services( Windows Communication Foundation

    脚本

    文档对象模型(DOM)

    视觉效果

    位图效果

    编辑

    RTF 格式剪贴板

    完全 XAML 支持


    部分信任环境下的编程

        对于 XBAP 应用程序(WPF Browser Application),超出默认的 Internet 区域权限集的代码将被CAS检测    到,并且将引发安全异常导致应用程序终止。 在保护用户的同时,这种方式却并没有提供最佳的用户体验。

         一般而言,可能会超过所允许的权限的代码很可能是那些在独立的应用程序和浏览器宿主应用程序之间共享的代码。CAS 和 WPF 提供几种技术来处理这种情况。


    使用CAS检测权限

        在某些情况下,库程序集中的共享代码可能同时用于独立的应用程序和 XBAP应用。 在这些情况下,代码可能执行需要比应用程序授予的权限集更多权限的功能。通过使用 Microsoft NET Framework  3.0的安全机制,应用程序可以检测它是否拥有特定的权限。特别的,它可以通过在所需的权限实例上调用 Demand 方法来测试它是否拥有特定的权限。在下面的示例代码中,将展示如何通过代码查询是否能将文件保存到本地磁盘:

    public   class  SharedClass
    {
        ...
        
    public static void Save()
            
    if( IsPermissionGranted(new FileIOPermission(FileIOPermissionAccess.Write, @"c: ewfile.txt") ) ) {
                
    // Write to local disk
                using (FileStream stream = File.Create(@"c: ewfile.txt"))
                
    using (StreamWriter writer = new StreamWriter(stream))
                
    {
                    writer.WriteLine(
    "I can write to local disk.");
                }

            }

            
    else
            
    {
                MessageBox.Show(
    "I can't write to local disk.");
            }

        }

        
        
    //  Detect whether or not this application has the requested permission
         bool  IsPermissionGranted(CodeAccessPermission requestedPermission)
        
    {
            
    try
            
    {
                
    // Try and get this permission
                requestedPermission.Demand();
                
    return true;
            }

            
    catch
            
    {
                
    return false;
            }

        }

    }
          
        如果应用程序没有所需的权限, Demand调用将引发安全异常。否则,权限将被授予。 IsPermissionGranted 方法 封装此行为并相应返回 true false

    优雅的功能降级

        对于可以从不同的区域执行的代码,关注的是能够检测代码是否具有所需的权限。虽然检测区域是一种解决方法,但如果可能的话,最好能够为用户提供一种替代方法。 例如,完全信任的应用程序通常能让用户在任何想要的位置上创建文件,而部分信任的应用程序只能在独立存储区中创建文件。 如果创建文件的代码位于共享的程序集 (.dll)中,而该程序集被完全信任 (独立的应用程序) 和部分信任 (浏览器的宿主应用程序)所共享,并且这两种应用程序都希望用户能够创建文件,那么共享代码在适当的位置创建一个文件之前应该检测它是在部分信任环境中运行还是在完全信任环境中运行。以下的代码演示了这两种情况:

    public   class  SharedClass
    {
        
    public   static   void  Save()
        {
            
    if ( IsPermissionGranted( new  FileIOPermission(FileIOPermissionAccess.Write,  @" c: ewfile.txt " ) ) ) {
                
    //  Write to local disk
                 using  (FileStream stream  =  File.Create( @" c: ewfile.txt " ))
                
    using  (StreamWriter writer  =   new  StreamWriter(stream))
                {
                    writer.WriteLine(
    " I can write to local disk. " );
                }
            }
            
    else
            {
                
    //  Persist application-scope property to 
                
    //  isolated storage
                IsolatedStorageFile storage  =  
                  IsolatedStorageFile.GetUserStoreForApplication();
                
    using  (IsolatedStorageFileStream stream  =  
                  
    new  IsolatedStorageFileStream(
                    
    " newfile.txt " , FileMode.Create, storage))
                
    using  (StreamWriter writer  =   new  StreamWriter(stream))
                {
                    writer.WriteLine(
                      
    " I can write to Isolated Storage " );
                }
            }
        }

        
    //  Detect whether or not this application has the requested permission
         bool  IsPermissionGranted(CodeAccessPermission requestedPermission)
        {
            
    try
            {
                
    //  Try and get this permission
                requestedPermission.Demand();
                
    return   true ;
            }
            
    catch
            {
                
    return   false ;
            }
        }
    }

     

        在很多情况下,您应该能够找到一个部分信任环境下的替代方法。在一个受控环境中(例如Intranet),自定义的托管程序集可以安装到客户端的全局程序集缓存 (GAC)中。 这些共享库可以执行需要完全信任的代码,并且通过使用 AllowPartiallyTrustedCallersAttribute (请参阅 Windows Presentation Foundation Security 和  Windows Presentation Foundation Security Strategy - Platform Security 获得详细信息)让只允许部分信任的应用程序所引用。


    浏览器主机检测

         当您需要在每权限基础上进行检查时,使用 CAS 来检查权限是一种合适的技术。 然而,这种技术依赖于将捕获异常作为正常处理流程的一部分,通常并不推荐这么做,并且可能会有性能方面的问题。如果您的 XAML 浏览器应用程序 (XBAP) 只运行在 Internet 区域沙箱中,那么您可以使用 System.Windows.Interop.BrowserInteropHelper.IsBrowserHosted ,对于 XAML 浏览器应用程序 (XBAPs)它返回true。以下是代码示例:

    namespace  SharedPages
    {
        
    using  System;
        
    using  System.Windows;
        
    using  System.Windows.Interop;
        
    using  System.Windows.Navigation;

        
    public   class  TaskLauncher : PageFunction < TaskContext >
        {
            TaskData taskData 
    =   new  TaskData();

            
    protected   override   void  Start()
            {
                
    //  Retain instance (and state) in navigation history until task is complete
                 this .KeepAlive  =   true ;
                
    this .WindowTitle  =   " Task Launcher " ;

                
    //  Is this assembly running in a browser-hosted application (XBAP)?
                 if  (BrowserInteropHelper.IsBrowserHosted)
                {
                    
    //  If so, use browser-style UI
                    UseTaskPageUI();
                }
                
    else
                {
                    
    //  If not, use window-style UI
                    UseTaskDialogBoxUI();
                }
            }

            
    #region  Task Page UI
            
    void  UseTaskPageUI()
            {
                
    //  Launch the task
                TaskPage taskPage  =   new  TaskPage( this .taskData);
                taskPage.Return 
    +=   new  ReturnEventHandler < TaskResult > (taskPage_Return);
                
    this .NavigationService.Navigate(taskPage);
            }
            
    void  taskPage_Return( object  sender, ReturnEventArgs < TaskResult >  e)
            {
                
    //  Task was completed (finished or canceled), return TaskResult and TaskData
                OnReturn( new  ReturnEventArgs < TaskContext > ( new  TaskContext(e.Result,  this .taskData)));
            }
            
    #endregion

            
    #region  Task Dialog Box UI
            
    void  UseTaskDialogBoxUI()
            {
                
    //  Create and show dialog box
                TaskDialog taskDialog  =   new  TaskDialog( this .taskData);
                taskDialog.Owner 
    =  Application.Current.MainWindow;
                
    bool  dialogResult  =  ( bool )taskDialog.ShowDialog();
                TaskResult taskResult 
    =  (dialogResult  ==   true   ?  TaskResult.Finished : TaskResult.Canceled);

                
    //  Return results
                OnReturn( new  ReturnEventArgs < TaskContext > ( new  TaskContext(taskResult,  this .taskData)));
            }
            
    #endregion
        }
    }

     


    注意:

    IsBrowserHosted 只判断应用程序是否在浏览器中运行,而不管应用程序是以哪一组权限在运行。


    管理权限

        默认情况下,XBAP应用程序运行于部分信任环境 (默认的 Internet 区域权限集)。 但是根据应用程序的要求,它可以更改权限集而不再使用默认值。 例如,如果一个 XBAP是从本地Intranet启动的,那么它就可以充分利用增加的权限集下, 如下表3所示。

    表 3: LocalIntranet 和 Internet 权限

    权限 属性 LocalIntranet Internet

    DNS

    访问 DNS 服务器

    环境变量

    读取

    文件对话框

    打开

    文件对话框

    不受限制

    独立存储

    由用户的程序集隔离

    独立存储

    未知的隔离

    独立存储

    无限制的用户配额

    媒体

    安全的音频、 视频和图像

    打印

    默认打印

    打印

    安全打印

    反射

    发出(Emit)

    安全

    托管代码执行

    安全

    断言授予的权限

    用户界面

    不受限制

    用户界面

    安全的顶级窗口

    用户界面

    拥有剪贴板

    Web 浏览器

    到 HTML的安全框架导航

            如果您要增加权限,您可以使用下列工具之一:


        如果您的 XBAP 需要完全信任,可以使用相同的工具来增加所请求的权限,尽管一个 XBAP应用程序只有被安装到本地计算机并且从本地计算机上启动时才能得到完全信任。这这意味着你失去了在将XBAP发布到 Web 服务器时所获得的自动更新支持。

    请参阅


    • 0
      点赞
    • 2
      收藏
      觉得还不错? 一键收藏
    • 0
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值