ASP.NET MVC에서 동적 로그인 URL로 리디렉션하는 방법


96

클라이언트 용 페이지를 호스팅하는 멀티 테넌시 웹 사이트를 만들고 있습니다. URL의 첫 번째 세그먼트는 다음 URL 라우팅 체계를 사용하여 Global.asax에 정의 된 클라이언트를 식별하는 문자열입니다.

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

이것은 / foo / Home / Index와 같은 URL에서 잘 작동합니다.

그러나 [Authorize] 속성을 사용할 때 동일한 매핑 체계를 사용하는 로그인 페이지로 리디렉션하고 싶습니다. 따라서 클라이언트가 foo이면 로그인 페이지는 web.config에 정의 된 고정 / Account / Login 리디렉션 대신 / foo / Account / Login이됩니다.

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

2
라우팅과 거의 똑같은 일을하기 때문에 이것이 필요했습니다! 감사!
Trevor de Koekkoek

고마워요, 비슷한 일을하는 방법을 알아 내려고했습니다.
Chance

그것은 나에게 자신의 구현에 대한 아이디어를주었습니다. 정말 감사합니다!
Alexander Beletsky

3
MVC 2 이상 사용하는 경우 반드시 설정 영역 = NULL (또는 올바른 지역)에 수 - 그렇지 않으면이 페이지에서 상속받을 수 있습니다 당신은 방문을 시도
Simon_Weaver

MVC없이이 작업을 수행 할 수있는 방법이 있습니까?
DARKGuy

답변:


30

주요 문제는 기본 제공 ASP.NET FormsAuthentication 클래스에 피기 백하려는 경우 (그렇게해서는 안되는 좋은 이유가 없습니다) 하루가 끝날 때 뭔가 호출 FormsAuthentication.RedirectToLoginPage()될 것이라는 것입니다. 구성된 URL을 확인합니다. 로그인 URL은 단 하나 뿐이며 이것이 바로 그들이 디자인 한 방식입니다.

문제 (아마도 Rube Goldberg 구현)에 대한 나의 찌르는 것은 모든 클라이언트가 공유하는 루트의 단일 로그인 페이지 (예 : / account / login)로 리디렉션하는 것입니다. 이 로그인 페이지는 실제로 아무것도 표시하지 않습니다. ReturnUrl 매개 변수 또는 세션에있는 일부 값 또는 클라이언트를 식별하는 쿠키를 검사하고이를 사용하여 특정 / client / account / login 페이지에 대한 즉각적인 302 리디렉션을 발행합니다. 추가 리디렉션이지만 눈에 띄지 않을 가능성이 높으며 기본 제공 리디렉션 메커니즘을 사용할 수 있습니다.

다른 옵션은 설명 할 때 고유 한 사용자 지정 특성을 만들고 클래스 에서 RedirectToLoginPage()메서드 를 호출하는 모든 것을 피하는 것입니다. FormsAuthentication이를 고유 한 리디렉션 논리로 대체 할 것입니다. (비슷한 자신 만의 클래스를 만들 수도 있습니다.) 정적 클래스이기 때문에 자신의 대체 인터페이스를 주입하고 기존 [Authorize] 속성과 함께 마법처럼 작동하도록 할 수있는 메커니즘을 알지 못합니다. 불면,하지만 사람들은 전에 비슷한 일을 수행했다 .

도움이 되었기를 바랍니다.


이것은 아마도 가장 안전한 접근 방식 일 것입니다. 자신의 [MyAuthorize] 속성을 만드는 것은 위험합니다. 빌드가 사람들이 내장 된 [Authorize] 속성을 사용하지 않는다는 것을 확인하지 않는 한, 사람들 (또는 자신)이 잘못된 것을 잊어 버리고 사용할 위험이 있습니다
Simon_Weaver 2011 년

어떤 경우에는 재정의하는 것이 도움이 될 수 있습니다 Application_AuthenticateRequest(아래 내 답변 참조).
turdus-merula 2019

41

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

편집 : web.config에서 기본 양식 인증 loginUrl을 비활성화 할 수 있습니다 . 누군가 사용자 지정 속성이 있다는 사실을 잊어 버리고 실수로 내장 된 [Authorize] 속성을 사용하는 경우를 대비하십시오.

web.config에서 값을 수정합니다.

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

그런 다음 오류를 기록하고 사용자를 가장 일반적인 로그인 페이지로 리디렉션하는 작업 방법 'ERROR'를 만듭니다.


2
MVC 2를 사용하는 경우 이상 (또는 영역이라고 무엇이든) 사전에 {지역, 널 (null)} 추가해야합니다 - 그렇지 않으면이 페이지에서 상속받을 수 있습니다 당신은 방문을 시도
Simon_Weaver

2

이 문제에 대한 나의 해결책은 사용자 정의 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; }
    }

0

하나를 사용하기로 결정하면 여전히 내장 된 ASP.NET있는 FormsAuthentication, 하나는 오버라이드 (override)하는 수 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;
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.