[.NET 基于角色安全性验证] 之一:基础知识
[ 2006-08-04 17:43:55 | 作者: yuhen ]
.NET 基于角色安全性验证的核心是主体(Principal)和标识(Identity)对象,其中主体负责角色或者组的验证,标识对象封装有关正在验证的用户或实体的信息。角色安全性验证通过生成可供当前线程使用的主体信息来支持授权,其中主体用关联的标识进行构造。
在 .NET Framework 中提供了两组 Principal/Identity 类型,分别是基于 Windows 操作系统账户的 WindowsPrincipal/WindowsIdentity,以及用来进行自定义验证的 GenericPrincipal/GenericIdentity。
主体(Principal)对象在应用程序域(AppDomain)中绑定到调用上下文(CallContext)对象,缺省情况下,应用程序域会自动创建采取默认安全策略的 GenericPrincipal/GenericIdentity对象,同时主体(Principal)对象引用从创建线程自动复制到新线程的调用上下文(CallContext)中。我们可以通过 Thread.CurrentPrincipal 获得缺省主体(Principal)和标识(Identity)对象信息。
接下来,我们使用 WindowsPrincipal/WindowsIdentity 做一些简单的验证,同时为了进一步理解基于角色安全性验证的用途。
我们修改上面这段代码,要求 Test() 方法必须是拥有管理员权限才能调用。
1. 我们使用 System.Security.Permissions.PrincipalPermissionAttribute 特性为 Test 方法加上角色验证标记,要求调用用户(Windows 操作系统登录用户)必须是 "Administrators" 组成员。
2. 在 Main 方法中设置线程的主体和标识对象。WindowsIdentity.GetCurrent() 用来获取当前登录用户的标识对象,如果登录用户属于 Adminstrators 组,则 Test() 方法正常调用,否则会触发 SecurityException 异常(我们可以使用 WindowsIdentity.GetAnonymous() 获取匿名用户标识对象来触发该异常)。
我们还可以使用其他的方法来做到这一点。
1. 使用 PrincipalPermission 对象替换 PrincipalPermissionAttribute,我们就可以使用动态权限验证,可以将用户名或者角色参数写入配置文件中。
2. 使用 AppDomain.CurrentDomain.SetThreadPrincipal 设置主体对象和 Thread.CurrentPrincipal 作用相同。我们还可以直接使用 AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal) 让系统自动使用当前登录用户名创建 WindowsPrincipal/WindowsIdentity。
或者
上面的例子都是基于角色或者组的验证,当然我们还可以基于用户进行验证。
当然,我们还可以同时用 role 和 name。PrincipalPermission 对象比 PrincipalPermissionAttribute 更加灵活,我们可以使用它进行多个权限的并集运算,以及进行 xml 转换等。
下面是使用 GenericPrincipal/GenericIdentity 改写的代码。
除了使用上述方法外,某些时候我们并不希望触发 SecurityException 异常,我们希望能给出另外的执行策略,那么可以直接使用 Principal.InRole 以及 Identity.Name 了。
总结一下,基于角色的安全检查有三种方法。
1. 使用命令式安全检查。该方法主要是通过 PrincipalPermission.Demand() 方法进行。
2. 使用声明性安全检查。通过 PrincipalPermissionAttribute 特性指定运行所需角色和用户名。
3. 直接访问 Principal 对象。访问 Thread.CurrentPrincipal 属性获得当前主体和标识对象,并调用其相关方法和属性进行进一步验证。
有关细节可参考 MSDN 文档,角色验证主要用于 ASP.NET 环境,雨痕将在后续 Blog 中做进一步说明。
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=274
public interface IPrincipal
{
// Methods
bool IsInRole(string role);
// Properties
IIdentity Identity { get; }
}
public interface IIdentity
{
// Properties
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}在 .NET Framework 中提供了两组 Principal/Identity 类型,分别是基于 Windows 操作系统账户的 WindowsPrincipal/WindowsIdentity,以及用来进行自定义验证的 GenericPrincipal/GenericIdentity。
主体(Principal)对象在应用程序域(AppDomain)中绑定到调用上下文(CallContext)对象,缺省情况下,应用程序域会自动创建采取默认安全策略的 GenericPrincipal/GenericIdentity对象,同时主体(Principal)对象引用从创建线程自动复制到新线程的调用上下文(CallContext)中。我们可以通过 Thread.CurrentPrincipal 获得缺省主体(Principal)和标识(Identity)对象信息。
Console.WriteLine(Thread.CurrentPrincipal); Console.WriteLine(Thread.CurrentPrincipal.Identity);
接下来,我们使用 WindowsPrincipal/WindowsIdentity 做一些简单的验证,同时为了进一步理解基于角色安全性验证的用途。
static void Test()
{
Console.WriteLine("Test...");
}
static void Main(string[] args)
{
Test();
}我们修改上面这段代码,要求 Test() 方法必须是拥有管理员权限才能调用。
1. 我们使用 System.Security.Permissions.PrincipalPermissionAttribute 特性为 Test 方法加上角色验证标记,要求调用用户(Windows 操作系统登录用户)必须是 "Administrators" 组成员。
2. 在 Main 方法中设置线程的主体和标识对象。WindowsIdentity.GetCurrent() 用来获取当前登录用户的标识对象,如果登录用户属于 Adminstrators 组,则 Test() 方法正常调用,否则会触发 SecurityException 异常(我们可以使用 WindowsIdentity.GetAnonymous() 获取匿名用户标识对象来触发该异常)。
[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
static void Test()
{
Console.WriteLine("Test...");
}
static void Main(string[] args)
{
Thread.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
Test();
}我们还可以使用其他的方法来做到这一点。
1. 使用 PrincipalPermission 对象替换 PrincipalPermissionAttribute,我们就可以使用动态权限验证,可以将用户名或者角色参数写入配置文件中。
2. 使用 AppDomain.CurrentDomain.SetThreadPrincipal 设置主体对象和 Thread.CurrentPrincipal 作用相同。我们还可以直接使用 AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal) 让系统自动使用当前登录用户名创建 WindowsPrincipal/WindowsIdentity。
static void Test()
{
new PrincipalPermission(null, "Administrators").Demand();
Console.WriteLine("Test...");
}
static void Main(string[] args)
{
AppDomain.CurrentDomain.SetThreadPrincipal(new WindowsPrincipal(WindowsIdentity.GetCurrent()));
Test();
}或者
static void Test()
{
new PrincipalPermission(null, "Administrators").Demand();
Console.WriteLine("Test...");
}
static void Main(string[] args)
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
Test();
}上面的例子都是基于角色或者组的验证,当然我们还可以基于用户进行验证。
[PrincipalPermission(SecurityAction.Demand, Name="YUHEN\\q.yuhen")]
new PrincipalPermission("YUHEN\\q.yuhen", null).Demand();当然,我们还可以同时用 role 和 name。PrincipalPermission 对象比 PrincipalPermissionAttribute 更加灵活,我们可以使用它进行多个权限的并集运算,以及进行 xml 转换等。
下面是使用 GenericPrincipal/GenericIdentity 改写的代码。
//[PrincipalPermission(SecurityAction.Demand, Name="q.yuhen", Role="admins")]
static void Test()
{
new PrincipalPermission(null, "Administrators").Demand();
Console.WriteLine("Test...");
}
static void Main(string[] args)
{
// 创建自定义用户标识对象。
GenericIdentity identity = new GenericIdentity("q.yuhen");
// 创建主体对象,并指定所拥有的角色数组。
string[] roles = new string[] { "admins" };
GenericPrincipal principal = new GenericPrincipal(identity, roles);
// 设定主体。
AppDomain.CurrentDomain.SetThreadPrincipal(principal);
Test();
}除了使用上述方法外,某些时候我们并不希望触发 SecurityException 异常,我们希望能给出另外的执行策略,那么可以直接使用 Principal.InRole 以及 Identity.Name 了。
static void Test()
{
if (Thread.CurrentPrincipal.IsInRole("admins") && Thread.CurrentPrincipal.Identity.Name == "q.yuhen")
{
Console.WriteLine("Test...");
}
else
{
Console.WriteLine("您没有执行权限!");
}
}总结一下,基于角色的安全检查有三种方法。
1. 使用命令式安全检查。该方法主要是通过 PrincipalPermission.Demand() 方法进行。
2. 使用声明性安全检查。通过 PrincipalPermissionAttribute 特性指定运行所需角色和用户名。
3. 直接访问 Principal 对象。访问 Thread.CurrentPrincipal 属性获得当前主体和标识对象,并调用其相关方法和属性进行进一步验证。
有关细节可参考 MSDN 文档,角色验证主要用于 ASP.NET 环境,雨痕将在后续 Blog 中做进一步说明。
[最后修改由 yuhen, 于 2007-08-14 13:26:54]
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=274
这篇日志没有评论。






