Context.User 在 Global.asax.Application_AuthenticateRequest 中分配后丢失角色
我在我的 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 文件中删除标签,一切都会正常。 当我尝试强制只有具有管理员角色的用户才能访问管理目录时,问题就出现了。
根据这篇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 之后,执行会直接跳转到登录页面(因为缺少角色会导致管理文件夹中的页面加载被拒绝)。 但是,当我在登录的 Page_Load 的第一行执行相同的语句时,它返回 false。 因此,在 Global.asax 中的 Application_AuthenticateRequest 和受限制目录中的 WebForm 初始加载之后,角色信息丢失,导致身份验证失败(注意:在 Page_Load 中,正确的身份验证票证仍分配给 Context.User.Id - 只有角色正在丢失)。
我做错了什么,如何让它正常工作?
更新:我输入了下面的解决方案
I am using Forms authentication in my asp.net (3.5) application. I am also using roles to define what user can access which subdirectories of the app. Thus, the pertinent sections of my web.config file look like this:
<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>
Based on what I have read, this should ensure that the only users able to access the Admin directory will be users who have been Authenticated and assigned the Admin role.
User authentication, saving the authentication ticket, and other related issues all work fine. If I remove the tags from the web.config file, everything works fine. The problem comes when I try to enforce that only users with the Admin role should be able to access the Admin directory.
Based on this MS KB article along with other webpages giving the same information, I have added the following code to my Global.asax file:
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
}
}
}
However, when I try to log in, I am unable to access the Admin folder (get redirected to login page).
Trying to debug the issue, if I step through a request, if I execute Context.User.IsInRole("Admin") at the line marked Debug#1 above, it returns a false. If I execute the same statement at line Debug#2, it equals true. So at least as far as Global.asax is concerned, the Role is being assigned properly.
After Global.asax, execution jumps right to the Login page (since the lack of role causes the page load in the admin folder to be rejected). However, when I execute the same statement on the first line of Page_Load of the login, it returns false. So somewhere after Application_AuthenticateRequest in Global.asax and the initial load of the WebForm in the restricted directory, the role information is being lost, causing authentication to fail (note: in Page_Load, the proper Authentication ticket is still assigned to Context.User.Id - only the role is being lost).
What am I doing wrong, and how can I get it to work properly?
Update: I entered the solution below
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是问题和解决方案:
在开发的早期,我进入“网站”菜单并单击“Asp.net 配置”。 这导致以下行被添加到 web.config:
从那时起,应用程序假设我是通过 Asp.net 站点管理器而不是通过 FormsAuthentication 角色来执行角色。 因此,尽管实际的身份验证和角色逻辑设置正确,但还是会反复失败。
从 web.config 中删除此行后,一切正常。
Here was the problem and solution:
Earlier in development I had gone to the Website menu and clicked on Asp.net configuration. This resulted in the following line being added to the web.config:
From that point on, the app was assuming that I was doing roles through the Asp.net site manager, and not through FormsAuthentication roles. Thus the repeated failures, despite the fact that the actual authentication and roles logic was set up correctly.
After this line was removed from web.config everything worked perfectly.
这只是随机截图,但是您是否因为管理员授权的顺序而被阻止? 也许您应该尝试切换“拒绝所有”和“所有管理员”。
以防万一它被拒绝覆盖。
(我这里有代码示例,但它们没有出现。
this is just a random shot, but are you getting blocked because of the order of authorization for Admin? Maybe you should try switching your deny all and your all Admin.
Just in case it's getting overwritten by the deny.
(I had code samples in here but they weren't showing up.