為了能更好地理解.NET基於角色的安全性,從一個最簡單的實例導入角色的應用。首先創建一個簡單的控制台程序,如代碼清單1-1所示。
代碼清單1-1 未添加角色驗證的程序
using System;
namespace角色實例
{
classProgram
{
static void Main(string[] args)
{
OutHello();
Console.Read();
}
staticvoid OutHello()
{
Console.WriteLine("hello world!");
}
}
}
如代碼清單1-1,這個程序只有兩個方法:Main方法和OutHello方法,OutHello方法輸出“hello world!”,在Main方法中調用OutHello方法。運行程序會打印字符串“hello world!”。下面對這個簡單的程序做略微的修改,為它添加一些聲明,如代碼清單1-2所示。
代碼清單1-2 運行主體和主體權限要求的主體不一致的代碼
using System;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
namespace 角色實例
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetAnonymous());
try
{
OutHello();
}
catch(SecurityException e)
{
Console.WriteLine(e.Message);
}
Console.Read();
}
[PrincipalPermission(SecurityAction.Demand,Role="Administrators")]
static void OutHello()
{
Console.WriteLine("hello world!");
}
}
}
在代碼清單1-2中,主要有三處變化:
1) 新添了三個名稱空間的引用,分別為System.Security.Permissions、System.Security.Principal和System.Threading。通過第4章的講解,我們對System.Security.Permissions名稱空間已經很熟悉了,這裡要使用其中的主體權限(PrincipalPermission)。System.Security.Principal是包含有關主體操作內容的名稱空間。System.Threading是有關線程操作的名稱空間。
2) 對於OutHello方法,聲明了PrincipalPermission權限,要求Administrators組成員才有權限執行此方法。
3) 對於Main方法,使用以下語句設置當前線程的主體為匿名用戶:
Thread.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetAnonymous())
下面來看代碼清單1-2的運行結果,如圖1-1所示。

圖1-1 代碼清單1-2運行結果
圖1-1表明,Main方法在調用OutHello方法時引發了SecurityException 異常。因為Main方法設置的主體為匿名用戶,而OutHello方法要求的是Administrators組用戶。下面把Main方法的執行線程設置為當前的Administrators用戶,再看看運行結果。修改後的Main方法如代碼清單1-3所示。
代碼清單1-3 運行主體和主體權限要求的主體一致的代碼
staticvoid Main(string[] args)
{
Thread.CurrentPrincipal = new System.Security.Principal.WindowsPrincipal(WindowsIdentity.GetCurrent());
try
{
OutHello();
}
catch (SecurityException e)
{
Console.WriteLine(e.Message);
}
Console.Read();
}
代碼清單1-3設置了Main方法運行線程的主體為當前用戶,本書測試的當前用戶為Administrator(最高權限用戶,屬於Administrators組),此時的運行結果如圖1-2所示。

圖1-2 代碼清單1-3的運行結果
通過代碼清單1-1、代碼清單1-2和代碼請單1-3的對比,可以粗略地了解主體驗證的作用。在前面的代碼中采用了聲明式安全檢查的方法,同其他權限一樣,這裡仍然可以使用命令式安全檢查的方法來達到同樣的效果,對於聲明式和命令式安全檢查還不太熟悉的讀者可以回顧第4章的相關內容。修改後的代碼如代碼清單1-4所示。
代碼清單1-4 使用命令式安全檢查來指定主體權限
namespace 角色實例
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentPrincipal = new System.Security.Principal.WindowsPrincipal(WindowsIdentity.GetCurrent());
try
{
OutHello();
}
catch (SecurityException e)
{
Console.WriteLine(e.Message);
}
Console.Read();
}
static void OutHello()
{
new PrincipalPermission("", "Administrators").Demand();
Console.WriteLine("hello world!");
}
}
}
查看本欄目
代碼清單1-4中,通過創建PrincipalPermission類的實例的方式來標識當前方法的主體權限請求。使用PrincipalPermission類比使用PrincipalPermissioAtrribute進行聲明的方法更加靈活,可以充分運用它的多個重載方法。下面繼續修改Main方法,使用標識對象,如代碼清單1-5所示。
代碼清單1-5 使用標識
namespace 角色實例
{
class Program
{
static void Main(string[] args)
{
GenericIdentity identity = new GenericIdentity("xuanhun");
string[] roles = new string[] { "Administrators" };
GenericPrincipal principal = new GenericPrincipal(identity, roles);
AppDomain.CurrentDomain.SetThreadPrincipal(principal);
OutHello();
Console.Read();
}
static void OutHello()
{
new PrincipalPermission("xx", "Administrators").Demand();
Console.WriteLine("hello world!"); } }
}
在代碼清單1-5的Main方法中,首先創建用戶自定義的標識對象identity,然後創建角色數組roles,並指定主體擁有的角色數組,最後設定當前應用程序域的主體。在OutHello方法中,要求標識名稱為xx;而在Main方法中指定的標識為xuanhun,運行程序將引發異常,如圖1-3所示。

圖1-3 標識不一致的運行結果
到目前為止,我們體驗了.NET的角色驗證,在感性上有了簡單的認識。更詳細內容,可以參考《.NET 安全揭秘》第五章。
作者:玄魂
出處:http://www.cnblogs.com/xuanhun/