Share via


WPF 部分信任安全性

一般來說,應該禁止網際網路應用程式直接存取重要系統資源,以防產生惡意損害。 根據預設,HTML 和用戶端指令碼語言無法存取重要系統資源。 因為 Windows Presentation Foundation (WPF) 瀏覽器裝載的應用程式可以從瀏覽器啟動,所以應該要受到類似的限制。 若要強制執行這些限制,WPF 會依賴Code Access Security (CAS) 和 ClickOnce (請參閱 WPF 安全性策略 – 平台安全性)。 根據預設,瀏覽器裝載的應用程式會要求 [網際網路] 區域 CAS 權限集合,不論這些應用程式是從網際網路、近端內部網路或本機電腦啟動。 不是以完整權限集合執行的應用程式就是所謂的以部分信任執行。

WPF 提供各種的支援,確保有最多的功能能夠安全地在部分信任的應用程式中使用,與 CAS 搭配使用則提供針對部分信任的額外程式設計支援。

此主題包括下列章節:

  • WPF 功能部分信任支援

  • 部分信任程式設計

  • 管理使用權限

WPF 功能部分信任支援

下表概略列出 Windows Presentation Foundation (WPF) 的功能,這些功能可以安全地在 [網際網路] 區域權限集合限制之下使用。

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

功能區域

功能

一般

瀏覽器視窗

原始站台存取

IsolatedStorage (512KB 限制)

UIAutomation 提供者

命令

輸入法 (IME)

Tablet 手寫筆和筆墨/筆跡

使用滑鼠捕捉和移動事件模擬拖放

OpenFileDialog

XAML 還原序列化 (透過 XamlReader.Load)

Web 整合

瀏覽器下載對話方塊

最上層使用者啟始的巡覽

mailto:links

統一資源識別元參數

HTTPWebRequest

IFRAME 中裝載的 WPF 內容

使用框架裝載相同站台的 HTML 網頁

使用 WebBrowser 裝載相同站台的 HTML 網頁

Web 服務 (ASMX)

Web 服務 (使用 Windows Communication Foundation)

指令碼

文件物件模型

視覺效果

2D 和 3D

動畫

媒體 (原始站台和跨網域)

影像/音訊/視訊

讀取

FlowDocument

XPS 文件

內嵌和系統字型

CFF 和 TrueType 字型

編輯

拼字檢查

RichTextBox

純文字和筆墨/筆跡剪貼簿支援

使用者啟始的貼上

複製選取的內容

控制項

一般控制項

上表涵蓋概略的 WPF 功能。 如需詳細資訊,請參閱 Windows Software Development Kit (SDK) 文件中有關於每個 WPF 成員所需權限的說明。 此外,下列功能也具有關於部分信任執行的詳細資訊,包括特殊考量。

下表概述無法安全地在 [網際網路] 區域權限集合限制之下執行的 WPF 功能。

表 2:在部分信任下不安全的 WPF 功能

功能區域

功能

一般

視窗 (應用程式定義的視窗和對話方塊)

SaveFileDialog

檔案系統

登錄存取

拖放

XAML 序列化 (透過 XamlWriter.Save)

UIAutomation 用戶端

來源視窗存取 (HwndHost)

完全語音支援

Windows Form 互通性

視覺效果

點陣圖效果

影像編碼

編輯

RTF 剪貼簿

完全 XAML 支援

部分信任程式設計

對於 XBAP 應用程式,超過預設使用權限集合的程式碼將會根據安全性區域而有不同的行為。 在某些情況下,使用者會在嘗試安裝此程式碼時收到警告。 使用者可以選擇繼續或取消安裝。 下表說明應用程式在每個安全性區域的行為,以及您要怎麼做才能讓應用程式獲得完全信任。

安全性區域

行為

取得完全信任

本機電腦

自動完全信任

不需任何動作。

內部網路和限制的網站

提示需有完全信任

使用憑證簽署 XBAP,以便使用者在提示中看見來源。

網際網路

失敗並顯示「未授與信任」

使用憑證簽署 XBAP。

注意事項注意事項

上表中說明的行為適用於未遵循 ClickOnce 信任部署模型的完全信任 XBAP。

一般來說,會超過允許之權限的程式碼通常都是供獨立應用程式和瀏覽器裝載的應用程式共用的通用程式碼。 CAS 和 WPF 提供數個方法可以管理這個案例。

使用 CAS 偵測權限

在某些情況下,程式庫組件中的共用程式碼可能同時由獨立應用程式和 XBAPs 兩者使用。 在這些情況下,程式碼執行功能時需要的權限可能會比應用程式權限集合所允許的權限還多。 您的應用程式可以使用 Microsoft .NET Framework 安全性來偵測它是否有特定的權限。 體來說,它可以在期望有某特定權限的執行個體上呼叫 Demand 方法來測試是否具有特定權限。 這會顯示在下列範例中,其中的程式碼會查詢它是否有權將檔案儲存至本機磁碟:


Imports System.IO ' File, FileStream, StreamWriter
Imports System.IO.IsolatedStorage ' IsolatedStorageFile
Imports System.Security ' CodeAccesPermission, IsolatedStorageFileStream
Imports System.Security.Permissions ' FileIOPermission, FileIOPermissionAccess
Imports System.Windows ' MessageBox

Namespace SDKSample
    Public Class FileHandling
        Public Sub Save()
            If IsPermissionGranted(New FileIOPermission(FileIOPermissionAccess.Write, "c:\newfile.txt")) Then
                ' Write to local disk
                Using stream As FileStream = File.Create("c:\newfile.txt")
                Using writer As New StreamWriter(stream)
                    writer.WriteLine("I can write to local disk.")
                End Using
                End Using
            Else
                MessageBox.Show("I can't write to local disk.")
            End If
        End Sub

        ' Detect whether or not this application has the requested permission
        Private Function IsPermissionGranted(ByVal requestedPermission As CodeAccessPermission) As Boolean
            Try
                ' Try and get this permission
                requestedPermission.Demand()
                Return True
            Catch
                Return False
            End Try
        End Function



...


    End Class
End Namespace
using System.IO; // File, FileStream, StreamWriter
using System.IO.IsolatedStorage; // IsolatedStorageFile
using System.Security; // CodeAccesPermission, IsolatedStorageFileStream
using System.Security.Permissions; // FileIOPermission, FileIOPermissionAccess
using System.Windows; // MessageBox

namespace SDKSample
{
    public class FileHandling
    {
        public void Save()
        {
            if (IsPermissionGranted(new FileIOPermission(FileIOPermissionAccess.Write, @"c:\newfile.txt")))
            {
                // Write to local disk
                using (FileStream stream = File.Create(@"c:\newfile.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。

功能上非失誤性降低

遇到能夠從不同區域執行的程式碼時,如果能夠偵測該程式碼是否有權執行需要的作業,將有很大的幫助。 偵測區域是一回事,如果可能的話最好能夠提供替代方法給使用者。 例如,完全信任的應用程式通常可以讓使用者在任何位置建立檔案,而部分信任應用程式則只能在獨立的儲存區中建立檔案。 如果由完全信任應用程式 (獨立應用程式) 和部分信任應用程式 (裝載瀏覽器的應用程式) 兩者共用的組件中,有建立檔案的程式碼,而且這兩種應用程式都想讓使用者可以建立檔案,則共用程式碼應先偵測它是在部分信任或完全信任下執行,再於適當位置建立檔案。 下列程式碼會示範這兩種情形。


Imports System.IO ' File, FileStream, StreamWriter
Imports System.IO.IsolatedStorage ' IsolatedStorageFile
Imports System.Security ' CodeAccesPermission
Imports System.Security.Permissions ' FileIOPermission, FileIOPermissionAccess
Imports System.Windows ' MessageBox

Namespace SDKSample
    Public Class FileHandlingGraceful
        Public Sub Save()
            If IsPermissionGranted(New FileIOPermission(FileIOPermissionAccess.Write, "c:\newfile.txt")) Then
                ' Write to local disk
                Using stream As FileStream = File.Create("c:\newfile.txt")
                Using writer As New StreamWriter(stream)
                    writer.WriteLine("I can write to local disk.")
                End Using
                End Using
            Else
                ' Persist application-scope property to 
                ' isolated storage
                Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
                Using stream As New IsolatedStorageFileStream("newfile.txt", FileMode.Create, storage)
                Using writer As New StreamWriter(stream)
                    writer.WriteLine("I can write to Isolated Storage")
                End Using
                End Using
            End If
        End Sub

        ' Detect whether or not this application has the requested permission
        Private Function IsPermissionGranted(ByVal requestedPermission As CodeAccessPermission) As Boolean
            Try
                ' Try and get this permission
                requestedPermission.Demand()
                Return True
            Catch
                Return False
            End Try
        End Function



...


    End Class
End Namespace
using System.IO; // File, FileStream, StreamWriter
using System.IO.IsolatedStorage; // IsolatedStorageFile
using System.Security; // CodeAccesPermission
using System.Security.Permissions; // FileIOPermission, FileIOPermissionAccess
using System.Windows; // MessageBox

namespace SDKSample
{
    public class FileHandlingGraceful
    {
        public void Save()
        {
            if (IsPermissionGranted(new FileIOPermission(FileIOPermissionAccess.Write, @"c:\newfile.txt")))
            {
                // Write to local disk
                using (FileStream stream = File.Create(@"c:\newfile.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;
            }
        }



...


    }
}

在許多情況下,您應該可以找到部分信任替代方法。

在受控制的環境中,例如內部網路,自訂 Managed 架構可以跨用戶端群安裝至global assembly cache (GAC) 中。 這些程式庫可執行需要完全信任的程式碼,並能透過 AllowPartiallyTrustedCallersAttribute 由只擁有部分信任的應用程式參考 (如需詳細資訊,請參閱 安全性 (WPF)WPF 安全性策略 – 平台安全性)。

瀏覽器裝載偵測

使用 CAS 檢查權限,是在需要以個別權限基準做檢查時相當適合的方法。 雖然這個方法依賴攔截例外狀況做為正常處理程序的一部分,但不建議在一般作業中使用,而且會有效能問題。 相反地,如果您的 XAML browser application (XBAP) 只在 [網際網路] 區域沙箱中執行,可以使用 BrowserInteropHelper.IsBrowserHosted 屬性,它會針對 XAML browser applications (XBAPs) 傳回 true。

注意事項注意事項

IsBrowserHosted 只會區分應用程式是否是在瀏覽器中執行,不會區分執行所使用的權限集合。

管理使用權限

根據預設,XBAPs 會以部分信任執行 (預設 [網際網路] 區域權限集合)。 不過,根據應用程式需求的不同,可能會變更預設的權限集合。 例如,XBAPs 如果是從近端內部網路啟動,就可以運用更高的權限集合,如下表所示。

表 3:近端內部網路和網際網路權限

使用權限

屬性

近端內部網路

網際網路

DNS

存取 DNS 伺服器

環境變數

讀取

檔案對話方塊

開啟

檔案對話方塊

不受限

隔離儲存區

依據使用者的組件隔離

隔離儲存區

未知的隔離

隔離儲存區

無限制的使用者配額

媒體

安全音訊、視訊及影像

列印

預設列印

列印

安全列印

反映

發出

安全性

Managed 程式碼執行

安全性

判斷提示授與的權限

使用者介面

不受限

使用者介面

安全的最上層視窗

使用者介面

專屬的剪貼簿

Web 瀏覽器

至 HTML 的安全架構巡覽

注意事項注意事項

使用者啟始的「剪下及貼上」只適用於部分信任的情況。

如果您需要提高權限,則需變更專案設定和 ClickOnce 應用程式資訊清單。 如需詳細資訊,請參閱 WPF XAML 瀏覽器應用程式概觀。 下列文件也能提供有用的資訊。

如果您的 XBAP 需要完整信任,可以使用相同的工具提高要求的權限。 不過,XBAP 只有在安裝於本機電腦並從本機電腦、內部網路或是瀏覽器的信任或允許網站中列出的 URL 啟動時,才會獲得完全信任。 如果應用程式是從內部網路或信任的網站安裝,則使用者將收到通知權限提升的標準 ClickOnce 提示。 使用者可以選擇繼續或取消安裝。

或者,您可以使用 ClickOnce 信任部署模型從任何安全性區域進行完全信任的部署。 如需詳細資訊,請參閱受信任的應用程式部署概觀安全性 (WPF)

請參閱

概念

安全性 (WPF)

WPF 安全性策略 – 平台安全性

WPF 安全性策略 – 安全性工程