Как перенаправить на динамический URL входа в систему ASP.NET MVC
Я создаю веб-сайт с несколькими арендаторами, на котором размещаются страницы для клиентов. Первый сегмент URL-адреса будет строкой, которая идентифицирует клиента, определенного в Global.asax использует следующую схему маршрутизации URL:
"{client}/{controller}/{action}/{id}"
это отлично работает, с URL-адресами, такими как /foo/Home/Index.
однако при использовании атрибута [Authorize] я хочу перенаправить на страницу входа, которая также использует ту же схему отображения. Поэтому, если клиент foo, страница входа будет /foo / Account / Login вместо фиксированного перенаправления/Account / Login, определенного в web.конфиг.
MVC использует HttpUnauthorizedResult для возврата 401 несанкционированного статуса, который, как я предполагаю, вызывает ASP.NET для перенаправления на страницу, определенную в web.конфиг.
Так кто-нибудь знает, как переопределить ASP.NET поведение перенаправления входа в систему? Или было бы лучше перенаправить в MVC, создав пользовательский атрибут авторизации?
EDIT-ответ: после немного покопавшись в источнике .Net, я решил, что пользовательский атрибут аутентификации является лучшим решением:
public class ClientAuthorizeAttribute: AuthorizeAttribute
{
public override void OnAuthorization( AuthorizationContext filterContext )
{
base.OnAuthorization( filterContext );
if (filterContext.Cancel && filterContext.Result is HttpUnauthorizedResult )
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "client", filterContext.RouteData.Values[ "client" ] },
{ "controller", "Account" },
{ "action", "Login" },
{ "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
});
}
}
}
3 ответов:
Я думаю, что основная проблема заключается в том, что если вы собираетесь piggyback на встроенный ASP.NET класс FormsAuthentication (и нет никаких веских причин, по которым вы не должны), что-то в конце дня собирается позвонить
FormsAuthentication.RedirectToLoginPage()который будет смотреть на один настроенный URL. Есть только один URL-адрес входа, когда-либо, и именно так они его разработали.мой удар по проблеме (возможно, реализация Rube Goldberg) состоял бы в том, чтобы позволить ему перенаправить на одну страницу входа в корневой каталог все клиенты, скажем / аккаунт / логин. Эта страница входа на самом деле ничего не отображает; она проверяет либо параметр ReturnUrl, либо некоторое значение, которое я получил в сеансе, либо файл cookie, который идентифицирует клиента и использует его для немедленного перенаправления 302 на конкретную страницу /client/account/login. Это дополнительный редирект, но, скорее всего, не заметный, и он позволяет использовать встроенные механизмы перенаправления.
другой вариант-создать свой собственный пользовательский атрибут, как вы описываете и избегайте всего, что вызывает
RedirectToLoginPage()методFormsAuthenticationкласс, так как вы будете заменять его своей собственной логикой перенаправления. (Вы можете создать свой собственный класс, который похож.) Поскольку это статический класс, я не знаю ни одного механизма, с помощью которого вы могли бы просто ввести свой собственный альтернативный интерфейс и заставить его волшебным образом работать с существующим атрибутом [Authorize], который дует, но люди делали подобные вещи перед.надеюсь, что это поможет!
в RTM версии ASP.NET MVC, свойство Cancel отсутствует. Этот код работает с ASP.NET MVC RTM:
using System; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Resources; namespace ePegasus.Web.ActionFilters { public class CustomAuthorize : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); if (filterContext.Result is HttpUnauthorizedResult) { filterContext.Result = new RedirectToRouteResult( new System.Web.Routing.RouteValueDictionary { { "langCode", filterContext.RouteData.Values[ "langCode" ] }, { "controller", "Account" }, { "action", "Login" }, { "ReturnUrl", filterContext.HttpContext.Request.RawUrl } }); } } } }
Edit: вы можете отключить проверку подлинности форм по умолчанию loginUrl в интернете.config-в случае, если кто-то забыл, что у вас есть пользовательский атрибут и использует встроенный атрибут [Authorize] по ошибке.
изменить значение в web.config:
<forms loginUrl="~/Account/ERROR" timeout="2880" />затем сделайте метод действия "ошибка", который регистрирует ошибку и перенаправляет пользователя на самую общую страницу входа, которая у вас есть.
мое решение этой проблемы было пользовательским
ActionResultкласс:sealed public class RequiresLoginResult : ActionResult { override public void ExecuteResult (ControllerContext context) { var response = context.HttpContext.Response; var url = FormsAuthentication.LoginUrl; if (!string.IsNullOrWhiteSpace (url)) url += "?returnUrl=" + HttpUtility.UrlEncode (ReturnUrl); response.Clear (); response.StatusCode = 302; response.RedirectLocation = url; } public RequiresLoginResult (string returnUrl = null) { ReturnUrl = returnUrl; } string ReturnUrl { get; set; } }
Comments