У нас есть приложение, которое использует членство 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
(моя пользовательская страница). Тем не менее, я все еще зарегистрирован.
Сетевые запросы
Несанкционированная страница. Обратите внимание, что выделенные желтые разделы показывают, что я все еще зарегистрирован. Это появляется только в том случае, если вы вошли в систему. Когда вы не вошли в систему, вы ничего не получите.
Проблема заключается в том, что приложение не знает, что делать, когда я уже зарегистрировался и попытаюсь перейти на страницу с атрибутом [AllowAnonymous]
. Если что-нибудь, поведение, которое я вижу здесь, предпочтительнее, это на самом деле дает мне страницу входа еще раз, потому что это будет путать, но тем не менее, это не идеально.
Редактировать 2 - Выполнение строки кода по строке
Ниже приведены результаты перехода по коду по строкам.
Страница /Account/Login
во время входа.
Первая точка останова в OnAuthorization
sub в 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 (Not isAuthorized AndAlso... IsAuthenticated), в результате чего перенаправление на RedirectUrl
.
После этого происходит возврат к тем же шагам, за исключением того, что на этот раз он вычисляется как false, то есть перенаправление не происходит, хотя я предполагаю, что это просто "неавторизованная" загрузка страницы и ее запуск тот же код снова.
Я попытался добавить следующий блок в начало Login
функции AccountController
.
If User.Identity.IsAuthenticated() Then
Return RedirectToAction("Index", "Home")
End If
Но, конечно, поскольку фильтр запускается до того, как действия происходят, этот код не попадает до тех пор, пока он не перенаправит меня на Unauthorized
(проверяется путем перехода).