Как перенаправить на динамический URL-адрес входа в ASP.NET MVC

Я создаю многопользовательский веб-сайт, на котором размещаются страницы для клиентов. Первый сегмент URL будет строкой, идентифицирующей клиента, определенной в Global.asax с использованием следующей схемы маршрутизации URL:

"{client}/{controller}/{action}/{id}"

Это прекрасно работает с URL-адресами, такими как / foo / Home / Index.

Однако при использовании атрибута [Authorize] я хочу перенаправить на страницу входа, которая также использует ту же схему сопоставления. Таким образом, если клиент foo, страница входа будет выглядеть так: / foo / Account / Login вместо фиксированного перенаправления / Account / Login, определенного в web.config.

MVC использует HttpUnauthorizedResult для возврата неавторизованного статуса 401, который, как я предполагаю, заставляет ASP.NET перенаправлять на страницу, определенную в web.config.

Так кто-нибудь знает, как переопределить поведение перенаправления входа в систему ASP.NET? Или лучше перенаправить в MVC, создав собственный атрибут авторизации?

РЕДАКТИРОВАТЬ - Ответ: после некоторого поиска в источнике .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 }
                });
        }
    }
}
делаю почти то же самое с маршрутизацией, так что мне это нужно! Спасибо!
Trevor de Koekkoek 27.12.2008 21:20:41
Спасибо, я пытался понять, как сделать что-то подобное.
Chance 3.02.2010 02:34:06
это дало мне идею для собственной реализации, большое спасибо!
Alexander Beletsky 31.10.2010 16:47:08
Обязательно установите area = null (или в правильную область), если используете MVC 2 и выше - иначе он будет унаследован от страницы, которую вы пытались посетить
Simon_Weaver 11.01.2011 02:11:05
Любой способ сделать это без MVC?
DARKGuy 22.09.2014 17:43:54
4 ОТВЕТА
РЕШЕНИЕ

Я думаю, что основная проблема заключается в том, что если вы собираетесь использовать встроенный класс ASP.NET FormsAuthentication (и нет веской причины, по FormsAuthentication.RedirectToLoginPage()которому вы не должны этого делать), то в конце дня будет вызываться что-то, что происходит посмотреть на один настроенный URL. Есть только один URL для входа в систему, и именно так они и разработали.

Моя проблема в этой проблеме (возможно, в реализации Rube Goldberg) состояла в том, чтобы позволить ей перенаправить на одну страницу входа в корень, доступную для всех клиентов, скажем / account / login. Эта страница входа не будет отображать ничего; он проверяет либо параметр ReturnUrl, либо какое-либо значение, полученное мной в сеансе, или cookie-файл, который идентифицирует клиента и использует его для немедленного перенаправления 302 на конкретную страницу / client / account / login. Это дополнительная переадресация, но, вероятно, не заметная, и она позволяет вам использовать встроенные механизмы перенаправления.

Другой вариант - создать собственный настраиваемый атрибут, как вы описываете, и избегать всего, что вызывает RedirectToLoginPage()метод FormsAuthenticationкласса, поскольку вы замените его своей собственной логикой перенаправления. (Вы можете создать свой собственный класс, который похож на этот.) Поскольку это статический класс, я не знаю ни одного механизма, с помощью которого вы могли бы просто внедрить свой собственный альтернативный интерфейс и заставить его волшебным образом работать с существующим атрибутом [Authorize], который удары, но люди делали подобные вещи раньше .

Надеюсь, это поможет!

30
11.12.2008 06:16:22
это, наверное, самый безопасный подход. Создание собственного атрибута [MyAuthorize] опасно. если ваша сборка не проверяет, что люди не используют встроенный атрибут [Authorize], вы рискуете, что люди (или вы сами) забудете и используете неправильный
Simon_Weaver 11.01.2011 01:13:54
В некоторых случаях может быть полезно переопределить Application_AuthenticateRequest(см. Мой ответ ниже).
turdus-merula 8.02.2019 07:57:02

В 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 }
                        });
            }
        }
    }
}

Редактировать: Вы можете отключить аутентификацию форм по умолчанию loginUrl в web.config - в случае, если кто-то забудет, что у вас есть пользовательский атрибут, и по ошибке использует встроенный атрибут [Authorize].

Измените значение в web.config:

 <forms loginUrl="~/Account/ERROR" timeout="2880" />

Затем создайте метод действия «ОШИБКА», который регистрирует ошибку и перенаправляет пользователя на самую общую страницу входа в систему.

40
11.01.2011 02:17:31
обязательно добавьте {area, null} в словарь (или как называется ваша область), если используете MVC 2 и выше - иначе он будет унаследован от страницы, которую вы пытались посетить
Simon_Weaver 11.01.2011 02:12:52

Моим решением этой проблемы был пользовательский 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; }
    }
2
16.07.2010 15:35:26

Тем не менее, если один решает использовать встроенный в ASP.NET FormsAuthentication, можно overide Application_AuthenticateRequestв Global.asax.csследующим образом :

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    string url = Request.RawUrl;

    if (url.Contains(("Account/Login"))
    {
        return;
    }

    if (Context.User == null)
    {
        // Your custom tenant-aware logic
        if (url.StartsWith("/foo"))
        {
            // Your custom login page.
            Response.Redirect("/foo/Account/Login");
            Response.End();
            return;
        }
    }
}
0
8.02.2019 07:56:17