.NET 提供基于角色的安全性,以帮助解决有关移动代码的安全问题,并提供支持,使组件能够确定哪些用户有权执行作。
类型安全和安全性
类型安全代码仅访问它有权访问的内存位置。 (对于此讨论,类型安全特别是指内存类型安全性,不应在更广泛的方面与类型安全混淆。例如,类型安全代码无法从另一对象的专用字段读取值。 它仅以定义明确的允许方式访问类型。
在实时(JIT)编译期间,可选验证过程检查要编译为本机计算机代码的方法的元数据和公共中间语言(CIL),以验证它们是否是类型安全的。 如果代码有权绕过验证,则会跳过此过程。 有关验证的详细信息,请参阅 托管执行过程。
尽管对类型安全性的验证并非必须运行托管代码,但类型安全性在程序集隔离和安全强制中起着重要作用。 当代码类型安全时,公共语言运行时可以完全隔离程序集彼此。 这种隔离有助于确保程序集不能对彼此产生负面影响,并增加应用程序可靠性。 即使类型安全组件在不同级别受信任,也可以在同一进程中安全地执行。 当代码类型不安全时,可能会出现不需要的副作用。 例如,运行时无法阻止托管代码调用本机(非托管)代码并执行恶意操作。 当代码具有类型安全时,运行时的安全实施机制能够确保它无法访问本机代码,除非它拥有执行此操作的权限。 所有类型不安全的代码必须被授予 SecurityPermission 权限,并传递枚举成员 SkipVerification 才能运行。
注释
代码访问安全性(CAS)已在 .NET Framework 和 .NET 的所有版本中弃用。 使用与 CAS 相关的 API 时,最新版本的 .NET 不遵循 CAS 注释并生成错误。 开发人员应寻求完成安全任务的替代方法。
校长
主体表示用户的标识和角色,并代表用户执行作。 .NET 中基于角色的安全性支持三种类型的主体:
泛型主体表示的是与 Windows 用户和角色独立存在的用户和角色。
Windows 主体表示 Windows 用户及其角色(或其 Windows 组)。 Windows 主体可以模拟另一个用户,这意味着主体可以代表用户访问资源,同时显示属于该用户的标识。
自定义主体可以通过任何特定应用程序所需的方式由应用程序定义。 他们可以扩展主体标识和角色的基本概念。
有关详细信息,请参阅 主体和标识对象。
身份验证
身份验证是通过检查用户的凭据并根据某些权威来验证这些凭据,从而发现和验证主体身份的过程。 验证过程中获取的信息可被您的代码直接使用。 还可以使用基于 .NET 角色的安全性对当前用户进行身份验证,并确定是否允许该主体访问代码。 如需查看如何对特定角色的主体进行身份验证的示例,请参阅 WindowsPrincipal.IsInRole 方法的重载。 例如,可以使用 WindowsPrincipal.IsInRole(String) 重载来确定当前用户是否是 Administrators 组的成员。
目前使用了各种身份验证机制,其中许多机制可用于基于 .NET 角色的安全性。 一些最常用的机制是基本身份验证、摘要身份验证、Passport、操作系统(如 NTLM 或 Kerberos)或应用程序定义的机制。
示例:
以下示例要求活动主体是管理员。 参数 name
是 null
,它允许作为管理员的任何用户传递需求。
注释
在 Windows Vista 中,用户帐户控制(UAC)确定用户的权限。 如果你是内置管理员组的成员,则分配有两个运行时访问令牌:标准用户访问令牌和管理员访问令牌。 默认情况下,你处于标准用户角色。 若要执行要求你是管理员的代码,必须先将特权从标准用户提升到管理员。 在启动应用程序时,可以右键单击应用程序图标并指示要以管理员身份运行。
using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;
class SecurityPrincipalDemo
{
public static void Main()
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
PrincipalPermission principalPerm = new PrincipalPermission(null, "Administrators");
principalPerm.Demand();
Console.WriteLine("Demand succeeded.");
}
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal
Class SecurityPrincipalDemo
Public Shared Sub Main()
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
Dim principalPerm As New PrincipalPermission(Nothing, "Administrators")
principalPerm.Demand()
Console.WriteLine("Demand succeeded.")
End Sub
End Class
以下示例演示如何确定主体的标识以及主体可用的角色。 此示例的一个应用场景可能是确认当前用户是否处于你允许使用此应用的角色。
using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;
class SecurityPrincipalDemo
{
public static void DemonstrateWindowsBuiltInRoleEnum()
{
AppDomain myDomain = Thread.GetDomain();
myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal myPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
Console.WriteLine($"{myPrincipal.Identity.Name.ToString()} belongs to: ");
Array wbirFields = Enum.GetValues(typeof(WindowsBuiltInRole));
foreach (object roleName in wbirFields)
{
try
{
// Cast the role name to a RID represented by the WindowsBuildInRole value.
Console.WriteLine($"{roleName}? {myPrincipal.IsInRole((WindowsBuiltInRole)roleName)}.");
Console.WriteLine("The RID for this role is: " + ((int)roleName).ToString());
}
catch (Exception)
{
Console.WriteLine($"{roleName}: Could not obtain role for this RID.");
}
}
// Get the role using the string value of the role.
Console.WriteLine($"'Administrators'? {myPrincipal.IsInRole("BUILTIN\\" + "Administrators")}.");
Console.WriteLine($"'Users'? {myPrincipal.IsInRole("BUILTIN\\" + "Users")}.");
// Get the role using the WindowsBuiltInRole enumeration value.
Console.WriteLine($"{WindowsBuiltInRole.Administrator}? {myPrincipal.IsInRole(WindowsBuiltInRole.Administrator)}.");
// Get the role using the WellKnownSidType.
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
Console.WriteLine($"WellKnownSidType BuiltinAdministratorsSid {sid.Value}? {myPrincipal.IsInRole(sid)}.");
}
public static void Main()
{
DemonstrateWindowsBuiltInRoleEnum();
}
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal
Class SecurityPrincipalDemo
Public Shared Sub DemonstrateWindowsBuiltInRoleEnum()
Dim myDomain As AppDomain = Thread.GetDomain()
myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
Dim myPrincipal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)
Console.WriteLine("{0} belongs to: ", myPrincipal.Identity.Name.ToString())
Dim wbirFields As Array = [Enum].GetValues(GetType(WindowsBuiltInRole))
Dim roleName As Object
For Each roleName In wbirFields
Try
' Cast the role name to a RID represented by the WindowsBuildInRole value.
Console.WriteLine("{0}? {1}.", roleName, myPrincipal.IsInRole(CType(roleName, WindowsBuiltInRole)))
Console.WriteLine("The RID for this role is: " + Fix(roleName).ToString())
Catch
Console.WriteLine("{0}: Could not obtain role for this RID.", roleName)
End Try
Next roleName
' Get the role using the string value of the role.
Console.WriteLine("{0}? {1}.", "Administrators", myPrincipal.IsInRole("BUILTIN\" + "Administrators"))
Console.WriteLine("{0}? {1}.", "Users", myPrincipal.IsInRole("BUILTIN\" + "Users"))
' Get the role using the WindowsBuiltInRole enumeration value.
Console.WriteLine("{0}? {1}.", WindowsBuiltInRole.Administrator, myPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
' Get the role using the WellKnownSidType.
Dim sid As New SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, Nothing)
Console.WriteLine("WellKnownSidType BuiltinAdministratorsSid {0}? {1}.", sid.Value, myPrincipal.IsInRole(sid))
End Sub
Public Shared Sub Main()
DemonstrateWindowsBuiltInRoleEnum()
End Sub
End Class
授权
授权是确定主体是否被允许执行请求操作的过程。 授权在身份验证后发生,并使用有关主体标识和角色的信息来确定主体可以访问哪些资源。 可以使用基于 .NET 角色的安全性来实现授权。