用户示例流程:
用户访问受保护的页面(整个应用程序都需要登录,甚至没有主页可以访问,直接重定向到登录页面)。这将重定向他们到https://www.example.com/Account/Login。
用户登录后,将被重定向到主页https://www.example.com/。他们已登录,一切运作正常。
用户单击书签,该书签恰好设置为https://www.example.com/Account/Login。
用户被重定向到通用的“未经授权”页面。
我在AccountController上使用了
<Authorize()>
属性,但在“Login”操作上使用了<AllowAnonymous()>
属性,正如我们之前看到的那样,当您未登录时,它可以正常工作,但是当您登录时似乎会有一些混乱。AccountController
<Authorize()> _
Public Class AccountController
'''other functions go here'''
<AllowAnonymous()> _
Public Function Login(ByVal returnUrl As String) As ActionResult
ViewData("ReturnUrl") = returnUrl
Return View()
End Function
AuthorizeRedirect 过滤器
<AttributeUsage(AttributeTargets.[Class] Or AttributeTargets.Method)> _
Public Class AuthorizeRedirect
Inherits AuthorizeAttribute
Private Const IS_AUTHORIZED As String = "isAuthorized"
Public RedirectUrl As String = "~/Home/Unauthorized"
Protected Overrides Function AuthorizeCore(httpContext As System.Web.HttpContextBase) As Boolean
Dim isAuthorized As Boolean = MyBase.AuthorizeCore(httpContext)
httpContext.Items.Add(IS_AUTHORIZED, isAuthorized)
Return isAuthorized
End Function
Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext)
MyBase.OnAuthorization(filterContext)
Dim isAuthorized = If(filterContext.HttpContext.Items(IS_AUTHORIZED) IsNot Nothing, Convert.ToBoolean(filterContext.HttpContext.Items(IS_AUTHORIZED)), False)
If Not isAuthorized AndAlso filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated Then
filterContext.RequestContext.HttpContext.Response.Redirect(RedirectUrl)
End If
End Sub
End Class
看到这一切,我想最简单的解决方案就是在我的登录动作中检查用户是否已经登录并自行重定向他们,像这样。
<AllowAnonymous()> _
Public Function Login(ByVal returnUrl As String) As ActionResult
If User.Identity.IsAuthenticated() Then
Return RedirectToAction("Index", "Home")
End If
ViewData("ReturnUrl") = returnUrl
Return View()
End Function
但是AuthorizeFilter总是先出现,这是可以理解的,但我无法弄清最后缺少的部分。我只想让它在用户已登录并前往登录页面时不显示“您没有权限查看此页面”,而是将其重定向到主页。我错过了什么?
编辑以使事情更加清晰
当已经登录时,我转到/Account/Login
。 这个302
重定向我到/Home/Unauthorized
(我的自定义页面)。 然而,我仍然登录。
网络请求
未经授权的页面。请注意,突出显示的黄色部分表明我仍然登录。只有在登录时才会出现这种情况。如果未登录,则不会看到任何内容。
问题似乎是应用程序不知道当我已经登录并尝试进入带有[AllowAnonymous]
属性的页面时该怎么做。如果说有什么好处的话,那么我在这里看到的行为比它再次给我一个登录页面要好,因为那会让人感到困惑,但是,仍然不理想。
编辑2-逐行浏览代码
以下是逐行浏览代码的结果。
页面/Account/Login
在登录状态下。
第一个断点在AuthorizeRedirect
过滤器中的OnAuthorization
子程序中。
Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext)
MyBase.OnAuthorization(filterContext)
Dim isAuthorized = If(filterContext.HttpContext.Items(IS_AUTHORIZED) IsNot Nothing, Convert.ToBoolean(filterContext.HttpContext.Items(IS_AUTHORIZED)), False)
If Not isAuthorized AndAlso filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated Then
filterContext.RequestContext.HttpContext.Response.Redirect(RedirectUrl)
End If
End Sub
Dim isAuthorized
开头的行返回False。 filterContext.HttpContext.Items(IS_AUTHORIZED)
不存在于项目列表中(为null)。
这意味着下一个If语句将计算为True(Not isAuthorized AndAlso ...IsAuthenticated),导致重定向到RedirectUrl
。
之后,它似乎会重新经历相同的步骤,但这次计算结果为false,这意味着重定向不会发生,尽管我猜这只是“未经授权”的页面加载并再次运行相同的代码。
我试图将以下块添加到AccountController
的Login
函数的顶部。
If User.Identity.IsAuthenticated() Then
Return RedirectToAction("Index", "Home")
End If
当然,由于过滤器是在动作之前运行的,所以这段代码只有在它已经将我重定向到“未经授权”的状态之后才会被执行(通过逐步调试进行验证)。
AuthorizeRedirect
应用在哪里? - Bozhidar StoyneffAuthorizeRedirect
代码,查看在加载登录页面时值是什么吗? - Francis Lord