📄 。net安全性.txt
字号:
如果使用的是窗体、Passport 或自定义身份验证,则必须在 Global.asax 的 Application_AuthenticateRequest 事件处理程序中编写代码以创建 IPrincipal 对象。GenericPrincipal 类是由 .NET Framework 提供的,在大多数情况下应该使用该类。
将 IPrincipal 对象放到当前的 HTTP 上下文中
将 IPrincipal 对象附加到当前的 HTTP 上下文中(使用 HttpContext.User 变量)。如果使用 Windows 身份验证,则 ASP.NET 自动完成此任务。否则,您必须手动附加该对象。
基于用户标识和/或角色成员身份进行授权
如果应用程序需要更细分的授权逻辑,请在代码中以声明方式(获取类或方法级授权)或强制方式使用 .NET 角色。
可以使用说明方式或强制方式主体权限要求(使用 PrincipalPermission 类),也可以通过调用 IPrincipal.IsInRole() 方法执行明确的角色检查。
下面的示例采用 Windows 身份验证并显示了声明方式的主体权限要求。仅当已进行身份验证的用户是 Manager Windows 组的成员时,才执行该属性后面的方法。如果调用方不是该组的成员,则引发 SecurityException。
[PrincipalPermission(SecurityAction.Demand,
Role=@"DomainName\Manager")]
public void SomeMethod()
{
}
下面的示例显示了代码中的明确角色检查。该示例采用 Windows 身份验证。如果使用非 Windows 身份验证机制,则代码大体上是一样的。只是将 User 对象转换为 GenericPrincipal 对象,而不是 WindowsPrincipal 对象。
// 从当前 HTTP 上下文中提取通过身份验证的用户。
// User 变量等价于 HttpContext.Current.
User(如果您在使用某个 // .aspx 或 .asmx 页)
WindowsPrincipal authenticatedUser = User as WindowsPrincipal;
if (null != authenticatedUser)
{
// 注意:要检索通过身份验证的用户的用户名,请使用
// 以下代码行
// string username = authenticatedUser.Identity.Name;
// 执行角色检查
if (authenticatedUser.IsInRole(@"DomainName\Manager") )
{
// 用户被授权执行管理功能
}
}
else
{
// 用户没有被授权执行管理功能
}
更多信息
? 有关以上窗体身份验证模式的实际实现,请参见本章后面的窗体身份验证部分。
创建自定义 IPrincipal 类
当使用非 Windows 身份验证机制时,大多数情况下应使用 .NET Framework 提供的 GenericPrincipal 类。它使用 IPrincipal.IsInRole 方法提供角色检查。
有时,您可能需要实现自己的 IPrincipal 类。实现您自己的 IPrincipal 类的原因包括:
? 您想扩展角色检查的功能。您可能需要一些方法来使您能够检查某一特定用户是否是一个多角色成员。例如:
CustomPrincipal.IsInAllRoles( "角色", "角色 2", "角色 3" )
CustomPrincipal.IsInAnyRole( "角色 1", "角色 2", "角色 3" )
? 您可能需要实现一个额外的方法或属性,以数组形式返回角色列表。例如:
string[] roles = CustomPrincipal.Roles;
? 您想让应用程序强制实施角色分级逻辑。例如,高级管理员被认为在层次结构中高于普通管理员。可以用如下方法进行测试。
CustomPrincipal.IsInHigherRole("Manager");
CustomPrincipal.IsInLowerRole("Manager");
? 您可能需要实现惰性的角色列表初始化。例如,只有在需要进行角色检查时,才能动态加载角色列表。
? 您可能需要实现 IIdentity 接口以用 X509ClientCertificate 标识用户。例如:
CustomIdentity id = CustomPrincipal.Identity;
X509ClientCertificate cert = id.ClientCertificate;
更多信息
有关创建您自己的 IPrincipal 类的详细信息,请参见本指南中的如何实现 IPrincipal。
返回页首
Windows 验证
如果应用程序用户使用可由服务器进行身份验证的 Windows 帐户(例如,在 Intranet 方案中),请使用 Windows 身份验证。
如果将 ASP.NET 配置为使用 Windows 身份验证,则 IIS 使用配置的 IIS 身份验证机制执行用户身份验证。图 8.4 中显示了这种情况。
图 8.4
ASP.NET Windows 身份验证使用 IIS 验证调用方的身份
已验证身份的调用方(如果将 IIS 配置为使用匿名身份验证,则它可能是匿名 Internet 用户帐户)的访问令牌可供 ASP.NET 应用程序使用。请注意以下方面:
? 这将允许 ASP.NET FileAuthorizationModule 使用原调用方的访问令牌,对请求的 ASP.NET 文件执行访问检查。
重要说明:ASP.NET 文件授权只对映射到 Aspnet_isapi.dll 的文件类型执行访问检查。
? 文件授权不要求使用模拟。如果启用了模拟,则应用程序执行的所有资源访问均使用被模拟的调用方的标识。在这种情况下,请确保附加到资源上的 ACL 包含一个访问控制项 (ACE),它可给原调用方标识至少授予读访问权限。
标识已验证身份的用户
ASP.NET 将 WindowsPrincipal 对象与当前的 Web 请求关联起来。这包含已验证身份的 Windows 用户的标识以及该用户所属的角色列表。在 Windows 身份验证中,角色列表是由用户所属的 Windows 组集合组成的。
以下代码显示如何获取已验证身份的 Windows 用户的标识,以及如何执行简单的角色授权测试。
WindowsPrincipal user = User as WindowsPrincipal;
if (null != user)
{
string username = user.Identity.Name;
// 执行角色检查
if ( user.IsInRole(@"DomainName\Manager") )
{
// 用户被授权执行管理功能
}
}
else
{
// 引发安全异常情况(由于我们没有 WindowsPrincipal)
}
返回页首
窗体身份验证
使用窗体身份验证时,如果未验证身份的用户试图访问受保护的文件或资源(其中,URL 授权拒绝用户访问),该用户所触发的事件顺序如图 8.5 所示。
图 8.5
窗体身份验证的事件顺序
下面说明了图 8.5 中显示的事件顺序:
1.
用户发出一个针对 Default.aspx 的 Web 请求。
由于启用了匿名访问,因此 IIS 允许进行此类请求。ASP.NET 检查 <authorization> 元素并查找 <deny users=?" /> 元素。
2.
将用户重定向到由 <forms> 元素的 loginUrl 属性指定的登录页 (Login.aspx)。
3.
用户提供凭据并提交登录窗体。
4.
根据数据存储(SQL Server 或 Active Directory)验证凭据,并检索角色(可选)。如果要使用基于角色的授权,则必须检索角色列表。
5.
使用 FormsAuthenticationTicket 创建一个 Cookie 并将其发回到客户端。将角色存储到票证中(可选)。通过在票证中存储角色列表,可以避免为相同用户的每个后续 Web 请求访问数据库来重新检索列表。
6.
客户端重定向将用户重定向到原请求页 (Default.aspx)。
7.
在 Application_AuthenticateRequest 事件处理程序(在 Global.asax 中)中,使用票证创建 IPrincipal 对象并将其存储在 HttpContext.User 中。
ASP.NET 检查 <authorization> 元素并查找 <deny users=?" /> 元素。但是,此时对用户进行身份验证。
ASP.NET 检查 <authorization> 元素以确保用户位于 <allow> 元素中。
给用户授予访问 Default.aspx 的权限。
窗体身份验证的开发步骤
以下列表重点介绍了实现窗体身份验证时必须执行的主要步骤:
1.
将 IIS 配置为使用匿名访问。
2.
将 ASP.NET 配置为使用窗体身份验证。
3.
创建登录 Web 窗体并验证提供的凭据。
4.
从自定义数据存储中检索角色列表。
5.
创建窗体身份验证票证(在票证中存储角色)。
6.
创建一个 IPrincipal 对象。
7.
将 IPrincipal 对象放到当前的 HTTP 上下文中。
8.
基于用户名/角色成员身份对用户进行授权。
将 IIS 配置为使用匿名访问
必须在 IIS 中将应用程序的虚拟目录配置为使用匿名访问。
? 将 IIS 配置为使用匿名访问
1.
启动 Internet 信息服务管理工具。
2.
选择应用程序的虚拟目录,右键单击,然后单击“属性”。
3.
单击“目录安全性”。
4.
在“匿名访问和验证控件”组中,单击“编辑”。
5.
选择“匿名访问”。
将 ASP.NET 配置为使用窗体身份验证
下面显示了一个配置示例。
<authentication mode="Forms">
<forms name="MyAppFormsAuth"
loginUrl="login.aspx"
protection="Encryption"
timeout="20"
path="/" >
</forms>
</authentication>
创建登录 Web 窗体并验证提供的凭据
根据 SQL Server 数据库或 Active Directory 验证凭据。
更多信息
? 请参见本指南中的如何将窗体身份验证用于 SQL Server 2000。
? 请参见本指南中的如何将窗体身份验证用于 Active Directory。
从自定义数据存储中检索角色列表
从 SQL Server 数据库表中获取角色,或从 Active Directory 内配置的组/分发列表中获取角色。有关详细信息,请参考前面的资源。
创建窗体身份验证票证
在票证中存储检索到的角色。下面的代码阐释了此过程。
// 用户单击“登录”按钮时,执行该事件处理程序,
// 随后提供一组凭据
private void Logon_Click(object sender, System.EventArgs e)
{
// 针对 SQL Server 数据库或 Active Directory
// 验证凭据
bool isAuthenticated = IsAuthenticated( txtUserName.Text,
txtPassword.Text );
if (isAuthenticated == true )
{
// 从 SQL Server 数据库或 Active Directory
// 检索该用户的角色集合。角色作为包含以管道符分隔的
// 角色名的字符串返回
// 例如“Manager|Employee|Sales|”
// 这样可以方便地将它们存储在身份验证票证中
string roles = RetrieveRoles( txtUserName.Text, txtPassword.Text );
// 创建身份验证票证并将角色存储在
// 该身份验证票证的自定义 UserData 属性中
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(
1, // 版本
txtUserName.Text, // 用户名
DateTime.Now, // 创建
DateTime.Now.AddMinutes(20),// 到期
false, // 永久
roles ); // 用户数据
// 对票证进行加密。
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
// 创建一个 cookie 并将加密的票证添加到
// 该 cookie 作为数据。
HttpCookie authCookie =
new HttpCookie(FormsAuthentication.FormsCookieName,
encryptedTicket);
// 将该 cookie 添加到传出 cookie 集合。
Response.Cookies.Add(authCookie);
// 将用户重定向到最初请求的页面
Response.Redirect( FormsAuthentication.GetRedirectUrl(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -