10

我们有一个使用ASP.net Membership提供基本登录机制的应用程序。它一切正常,但最近我们发现,如果您在登录时尝试登录登录页面,则会重定向到“未经授权”页面。ASP.NET会员登录用户登录时将登录重定向为未授权

示例用户流程。

用户转到安全页面(整个应用程序需要登录,有 甚至没有您可以访问的主页,只是直接重定向到登录)。 这将它们重定向到https://www.example.com/Account/Login

用户登录并重定向到主页https://www.example.com/。 他们已登录,一切正常。

用户点击恰好被设置为 https://www.example.com/Account/Login

用户被重定向到未经授权的仿制网页书签。

我有<Authorize()>属性在我的AccountController但<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(我的自定义页面)。不过,我仍然登录。

网络请求

Network request to Login page, which 302 redirects to Unauthorized

未经授权的网页。请注意,突出显示的黄色部分显示我仍然登录。仅当您登录后才会显示此内容。未登录时,您将看不到任何内容。

Unauthorized page

的问题似乎是,应用程序不知道该怎么办的时候,我已经登录,并试图去拥有它的[AllowAnonymous]属性页。如果有的话,我在这里看到的行为比它实际上给我一个登录页面更好,因为这会让人困惑,但仍然不理想。


编辑2 - 由线

这里通过代码线步进是通过线的代码线步进的结果。

/Account/Login同时登录。

第一个断点在OnAuthorization子在AuthorizeRedirect过滤器。

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)什么也没有(在项目列表中不存在)。

然后这意味着下一个If语句的计算结果为True(不是isAuthorizedandAlso ... IsAuthenticated),导致重定向到RedirectUrl

发生这种情况后,它似乎回到了相同的步骤,除了这次它评估为false,这意味着重定向不会发生,虽然我猜这只是'未经授权'页面加载和运行再次使用相同的代码。

我试图将下面的块添加到AccountControllerLogin函数的顶部。

If User.Identity.IsAuthenticated() Then 
     Return RedirectToAction("Index", "Home") 
    End If 

但是,当然,因为之前发生的动作这段代码是打不到直到后,它已经重定向我Unauthorized(由步进通过验证)过滤器运行。

+0

'AuthorizeRedirect'应用于何处? –

+0

现在还没有访问代码,但我很确定它是在标准FilterConfig中设置的,类似'filters.add(Authorizeredredirect)' –

+0

似乎用户未经授权。真的吗?你是否可以在重定向到未经授权的情况下点击/ home/index? –

回答

2

的基类AuthorizationAttribute在其OnAuthorization方法验证码:

bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true) 
         || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true); 

if (skipAuthorization) 
{ 
    return; 
} 

if (AuthorizeCore(filterContext.HttpContext)) 
// ... 

因此如果控制器动作已经在其定义的AllowAnonymousAttribute,你AuthorizeCore方法将不会被调用。因此filterContext.HttpContext.Items(IS_AUTHORIZED)将永远不会被设置。

您可以简单地复制here中的代码来实现OnAuthorization而不调用基类。这样你就可以用你想要的方式处理缓存。

顺便说一句,我的印象是,如果授权失败,请求管道中的后续进程无论如何都会重定向到登录页面。这就是为什么OnAuthorization的基本实现将filterContext.Result设置为新的HttpUnauthorizedResult实例。所以你不能完全清楚你为什么重写OnAuthorization并且首先做重定向。如果您想要某种定制授权代码,只需返回truefalseAuthorizeCore就足够了。

相关问题