[.NET 基于角色安全性验证] 之一:基础知识

简介:
.NET 基于角色安全性验证的核心是主体(Principal)和标识(Identity)对象,其中主体负责角色或者组的验证,标识对象封装有关正在验证的用户或实体的信息。角色安全性验证通过生成可供当前线程使用的主体信息来支持授权,其中主体用关联的标识进行构造。
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 属性获得当前主体和标识对象,并调用其相关方法和属性进行进一步验证。
 
目录
相关文章
|
5天前
|
开发框架 .NET 数据库连接
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
|
1月前
|
开发框架 JSON .NET
|
2月前
|
机器学习/深度学习 JSON 测试技术
CNN依旧能战:nnU-Net团队新研究揭示医学图像分割的验证误区,设定先进的验证标准与基线模型
在3D医学图像分割领域,尽管出现了多种新架构和方法,但大多未能超越2018年nnU-Net基准。研究发现,许多新方法的优越性未经严格验证,揭示了验证方法的不严谨性。作者通过系统基准测试评估了CNN、Transformer和Mamba等方法,强调了配置和硬件资源的重要性,并更新了nnU-Net基线以适应不同条件。论文呼吁加强科学验证,以确保真实性能提升。通过nnU-Net的变体和新方法的比较,显示经典CNN方法在某些情况下仍优于理论上的先进方法。研究提供了新的标准化基线模型,以促进更严谨的性能评估。
92 0
|
2月前
|
JSON 数据格式 微服务
.NET下 支持大小写不敏感的JSON Schema验证方法
有很多应用程序在验证JSON数据的时候用到了JSON Schema。 在微服务架构下,有时候各个微服务由于各种历史原因,它们所生成的数据对JSON Object属性名的大小写规则可能并不统一,它们需要消费的JSON数据的属性名可能需要大小写无关。 遗憾的是,目前的JSON Schema没有这方面的标准,标准中都是大小写敏感的。在类似上述情况下,这给使用JSON Schema进行数据验证造成了困难。
|
3月前
|
开发框架 .NET 物联网
.NET从入门到精通,零基础也能搞定的基础知识教程
.NET从入门到精通,零基础也能搞定的基础知识教程
92 0
|
3月前
|
Windows
windows server 2019 安装NET Framework 3.5失败,提示:“安装一个或多个角色、角色服务或功能失败” 解决方案
windows server 2019 安装NET Framework 3.5失败,提示:“安装一个或多个角色、角色服务或功能失败” 解决方案
714 0
|
3月前
|
Oracle 关系型数据库 数据管理
.NET医院检验系统LIS源码,使用了oracle数据库,保证数据的隔离和安全性
LIS系统实现了实验室人力资源管理、标本管理、日常事务管理、网络管理、检验数据管理(采集、传输、处理、输出、发布)、报表管理过程的自动化,使实验室的操作人员和管理者从繁杂的手工劳作中解放出来,提高了检验人员的工作效率和效益,降低了劳动成本和差错发生率。
|
3月前
|
开发框架 JavaScript .NET
Asp.Net就业课之三验证控件
Asp.Net就业课之三验证控件
61 0
|
3月前
|
开发框架 安全 C#
掌握.NET基础知识(一)
掌握.NET基础知识(一)
79 0
|
开发框架 JSON 算法
ASP.NET Core Web API之Token验证
ASP.NET Core Web API之Token验证
216 0