我在我的 asp.net (3.5) 应用程序中使用表单身份验证。我还使用角色来定义哪些用户可以访问应用程序的哪些子目录。因此,我的 web.config 文件的相关部分如下所示:
<system.web>
<authentication mode="Forms">
<forms loginUrl="Default.aspx" path="/" protection="All" timeout="360" name="MyAppName" cookieless="UseCookies" />
</authentication>
<authorization >
<allow users="*"/>
</authorization>
</system.web>
<location path="Admin">
<system.web>
<authorization>
<allow roles="Admin"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
根据我所阅读的内容,这应该确保唯一能够访问 Admin 目录的用户将是已经过身份验证并分配了 Admin 角色的用户。
用户身份验证、保存身份验证票证和其他相关问题都可以正常工作。如果我从 web.config 文件中删除标签,一切正常。当我尝试强制只有具有 Admin 角色的用户才能访问 Admin 目录时,问题就出现了。
基于此MS 知识库文章以及提供相同信息的其他网页,我已将以下代码添加到我的 Global.asax 文件中:
protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
if (HttpContext.Current.User != null) {
if (Request.IsAuthenticated == true) {
// Debug#1
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Context.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
// In this case, ticket.UserData = "Admin"
string[] roles = new string[1] { ticket.UserData };
FormsIdentity id = new FormsIdentity(ticket);
Context.User = new System.Security.Principal.GenericPrincipal(id, roles);
// Debug#2
}
}
}
但是,当我尝试登录时,我无法访问 Admin 文件夹(重定向到登录页面)。
尝试调试问题时,如果我单步执行请求,如果我在上面标记为 Debug#1 的行处执行 Context.User.IsInRole("Admin"),它会返回 false。如果我在 Debug#2 行执行相同的语句,它等于 true。因此,至少就 Global.asax 而言,角色已正确分配。
在 Global.asax 之后,执行直接跳转到 Login 页面(因为缺少角色会导致 admin 文件夹中的页面加载被拒绝)。但是,当我在登录的 Page_Load 的第一行执行相同的语句时,它返回 false。因此,在 Global.asax 中的 Application_AuthenticateRequest 和受限目录中 WebForm 的初始加载之后的某个地方,角色信息正在丢失,导致身份验证失败(注意:在 Page_Load 中,正确的身份验证票证仍然分配给 Context.User.Id - 只有角色正在丢失)。
我做错了什么,我怎样才能让它正常工作?
更新:我输入了下面的解决方案