共用方式為


WPF 部分信任安全性

一般而言,網際網路應用程式應該限制不得直接存取重要的系統資源,以防止惡意損害。 根據預設,HTML 和用戶端指令碼語言都不能存取重要的系統資源。 因為 Windows Presentation Foundation (WPF) 瀏覽器裝載的應用程式可以從瀏覽器啟動,它們應該符合一組類似的限制。 若要強制執行這些限制,WPF 程式碼存取安全性 (CAS) 和 ClickOnce (請參閱 WPF 安全性策略 - 平台安全性 (部分機器翻譯))。 根據預設,瀏覽器裝載的應用程式會要求網際網路區域 CAS 權限集合,而不論是從網際網路、近端內部網路或是在本機電腦啟動。 使用少於完整權限集執行的應用程式便是以部分信任執行。

WPF 提供各種不同的支援,以確保在部分信任中盡可能安全地使用最多的功能,並連同 CAS,提供額外的部分信任程式設計支援。

本主題包含下列幾節:

WPF 功能部分信任支援

下表列出 Windows Presentation Foundation (WPF) 的高階功能,可放心地在網際網路區域權限集合的限制範圍內使用。

表 1:在部分信任中安全的 WPF 功能

功能區域 功能
一般 瀏覽器視窗

原始站台存取

IsolatedStorage (512 KB 限制)

UIAutomation 提供者

命令

輸入法 (IME)

平板電腦手寫筆和筆跡

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

OpenFileDialog

XAML 還原序列化 (透過 XamlReader.Load)
Web 整合 瀏覽器下載對話方塊

最上層使用者啟始的瀏覽

mailto:links

統一資源識別項參數

HTTPWebRequest

在 IFRAME 中裝載的 WPF 內容

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

使用網頁瀏覽器裝載相同站台的 HTML 頁面

Web 服務 (ASMX)

Web 服務 (使用 Windows Communication Foundation)

指令碼

文件物件模型
視覺效果 2D 和 3D

動畫

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

影像處理/音訊/視訊
讀取 FlowDocuments

XPS 文件

內嵌與系統字型

CFF 與 TrueType 字型
編輯 拼字檢查

RichTextBox

純文字和筆跡剪貼簿支援

使用者啟始的貼上

複製選取的內容
控制項 一般控制項

下表涵蓋高階的 WPF 功能。 如需詳細資訊,Windows SDK 記錄了 WPF 中每個成員所需的權限。 此外,下列功能有關於部分信任執行的更詳細資訊,包括特殊考量。

下表列出無法放心地在網際網路區域權限集合的限制範圍內執行的 WPF 功能。

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

功能區域 功能
一般 視窗 (應用程式定義的視窗和對話方塊)

SaveFileDialog

檔案系統

登錄存取

拖放功能

XAML 序列化 (透過 XamlWriter.Save)

UIAutomation 用戶端

來源視窗存取 (HwndHost)

完整的語音支援

Windows Forms 互通性
視覺效果 點陣圖效果

影像編碼
編輯 RTF 格式剪貼簿

完整的 XAML 支援

部分信任程式設計

對於 XBAP 應用程式,超過預設權限集合的程式碼將會有不同的行為,視安全性區域而定。 在某些情況下,使用者會在嘗試安裝它時收到一則警告。 使用者可以選擇繼續或取消安裝。 下表描述每個安全性區域的應用程式行為,以及您必須針對應用程式執行什麼動作才能得到完全信任。

警告

XBAP 需要舊版瀏覽器才能運作,例如 Internet Explorer 和舊版的 Firefox。 Windows 10 和 Windows 11 通常不支援這些較舊的瀏覽器。 由於安全性風險,現代瀏覽器不再支援 XBAP 應用程式所需的技術。 不再支援啟用 XBAP 的外掛程式。 如需詳細資訊,請參閱 WPF 瀏覽器裝載應用程式 (XBAP) 常見問題集 (部分機器翻譯)。

安全性區域 行為 取得完全信任
本機電腦 自動的完全信任 不需要採取任何動作。
內部網路和信任的網站 完全信任的提示 使用憑證簽署 XBAP,讓使用者在提示中看到來源。
網際網路 因為「未授與信任」而失敗 使用憑證簽署 XBAP。

注意

上表中描述的行為是針對未遵循 ClickOnce 受信任部署模型的完全信任 XBAP。

一般而言,可能超過允許權限的程式碼很可能是在獨立式與瀏覽器裝載的應用程式之間共用的通用程式碼。 CAS 和 WPF 提供數種方法來管理這種案例。

使用 CAS 偵測權限

在某些情況下,獨立式應用程式與 XBAP 可能都會使用程式庫組件中的共用程式碼。 在這些情況下,程式碼執行的功能,所需的權限可能會超過應用程式的已授與權限集合所允許的權限。 您的應用程式可以使用 Microsoft .NET Framework 安全性偵測到它是否已有特定的權限。 具體來說,它可以藉由對所需權限的執行個體呼叫 Demand (部分機器翻譯) 方法,測試是否有特定權限。 這會顯示在下列的範例中,程式碼會查詢它是否能夠將檔案儲存到本機磁碟︰

using System.IO;
using System.IO.IsolatedStorage;
using System.Security;
using System.Security.Permissions;
using System.Windows;

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;
            }
        }


Imports System.IO
Imports System.IO.IsolatedStorage
Imports System.Security
Imports System.Security.Permissions
Imports System.Windows

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

如果應用程式沒有所需的權限,呼叫 Demand (部分機器翻譯) 將會擲回安全性例外狀況。 否則,便已授與權限。 IsPermissionGranted 會封裝這個行為,並視情況傳回 truefalse

功能正常降級

能夠偵測程式碼是否有權執行它需要做的事,對於可以從不同區域執行的程式碼而言很有趣。 不過偵測區域是一件事,可能的話,為使用者提供替代方式會好上許多。 比方說,完全信任應用程式通常可讓使用者在任何想要的地方建立檔案,而部分信任應用程式則只能在隔離儲存區建立檔案。 如果建立檔案的程式碼存在於完全信任 (獨立式) 應用程式和部分信任 (瀏覽器裝載) 應用程式所共用的組件中,而且兩個應用程式都想要讓使用者能夠建立檔案,則共用的程式碼應該先偵測它是在部分信任還是完全信任中執行,然後才能在適當位置中建立檔案。 下列程式碼可示範兩種情況。

using System.IO;
using System.IO.IsolatedStorage;
using System.Security;
using System.Security.Permissions;
using System.Windows;

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;
            }
        }


Imports System.IO
Imports System.IO.IsolatedStorage
Imports System.Security
Imports System.Security.Permissions
Imports System.Windows

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

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

在受控制的環境中,例如內部網路,可以跨用戶端基底將自訂的受管理架構安裝到全域組件快取 (GAC)。 這些程式庫可以執行要求完全信任的程式碼,並且從只允許部分信任的應用程式參考,方法是使用 AllowPartiallyTrustedCallersAttribute (部分機器翻譯) (如需詳細資訊,請參閱安全性 (部分機器翻譯) 和 WPF 安全性策略 - 平台安全性 (部分機器翻譯))。

瀏覽器裝載偵測

使用 CAS 來檢查權限,是當您需要檢查每項權限時適合的一項技巧。 不過,這項技巧依賴在一般處理時攔截例外狀況,一般而言不建議這麼做,其可能會發生效能問題。 相反,如果您的 XAML 瀏覽器應用程式 (XBAP) 僅在 Internet 區域沙箱內執行,則可以使用 BrowserInteropHelper.IsBrowserHosted(部分機器翻譯) 屬性,其會為 XAML 瀏覽器應用程式 (XBAP) 傳回 true。

警告

XBAP 需要舊版瀏覽器才能運作,例如 Internet Explorer 和舊版的 Firefox。 Windows 10 和 Windows 11 通常不支援這些較舊的瀏覽器。 由於安全性風險,現代瀏覽器不再支援 XBAP 應用程式所需的技術。 不再支援啟用 XBAP 的外掛程式。 如需詳細資訊,請參閱 WPF 瀏覽器裝載應用程式 (XBAP) 常見問題集 (部分機器翻譯)。

注意

IsBrowserHosted (部分機器翻譯) 只會區別應用程式是否正在瀏覽器中執行,而不會區別應用程式執行所使用的權限集合。

管理權限

根據預設,XBAP 會以部分信任 (預設網際網路區域權限集合) 來執行。 不過,根據應用程式的需求,也可以變更預設的權限集合。 例如,如果 XBAP 是從近端內部網路啟動,則它可以利用提高的權限集合,如下表所示。

警告

XBAP 需要舊版瀏覽器才能運作,例如 Internet Explorer 和舊版的 Firefox。 Windows 10 和 Windows 11 通常不支援這些較舊的瀏覽器。 由於安全性風險,現代瀏覽器不再支援 XBAP 應用程式所需的技術。 不再支援啟用 XBAP 的外掛程式。 如需詳細資訊,請參閱 WPF 瀏覽器裝載應用程式 (XBAP) 常見問題集 (部分機器翻譯)。

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

權限 屬性 LocalIntranet 網際網路
DNS 存取 DNS 伺服器 No
環境變數 參閱 No
檔案對話方塊 開啟
檔案對話方塊 不受限制 No
隔離儲存區 依據使用者隔離組件 No
隔離儲存區 未知的隔離
隔離儲存區 無限制的使用者配額 No
媒體 安全的音訊、視訊和影像
列印 預設列印 No
列印 安全列印
反映 發出 No
安全性 Managed 程式碼執行
安全性 判斷提示授與權限 No
使用者介面 不受限制 No
使用者介面 安全的最上層視窗
使用者介面 擁有剪貼簿
Web Browser HTML 框架安全瀏覽

注意

在部分信任中,只有在使用者啟動時,才允許剪下和貼上。

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

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

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

另請參閱