Frage

Ich erstelle eine Multi-Tenant-Website, die Seiten für Kunden ausrichtet. Das erste Segment der URL eine Zeichenkette sein, die den Client identifiziert, definiert in Global.asax die folgende URL-Routing-Schema verwendet:

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

Das funktioniert gut, mit URLs wie / foo / Home / Index.

Wenn jedoch die [autorisieren] Attribut, möchte ich auf eine Anmeldeseite umgeleitet werden, die auch die gleiche Zuordnungsschema verwendet. Also, wenn der Kunde foo ist, würde die Login-Seite sein / foo / Konto / Login anstelle der festen / Konto / Login Redirect in web.config definiert.

MVC eine HttpUnauthorizedResult verwendet einen 401 nicht autorisierten Status zurückzukehren, die ich nehme an ASP.NET führt auf der Seite in web.config definiert umleiten.

So weiß jemand, entweder, wie die ASP.NET Login Redirect Verhalten außer Kraft zu setzen? Oder wäre es besser, in MVC zu umleiten, indem Sie ein benutzerdefinierten Berechtigungs Attribut erstellen?

EDIT - Antwort: , nachdem sie in der .Net Quelle einige graben, habe ich beschlossen, dass eine benutzerdefinierte Authentifizierung Attribut ist die beste Lösung:

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 }
                });
        }
    }
}
War es hilfreich?

Lösung

Ich denke, das Hauptproblem, dass, wenn Sie auf der integrierten ASP.NET FormsAuthentication Klasse huckepack gehen (und es keinen guter Grund, sollten Sie nicht), etwas am Ende des Tages rufen werden FormsAuthentication.RedirectToLoginPage(), die an dem einem konfigurierten URL aussehen wird. Es gibt nur eine Anmelde-URL, überhaupt, und das ist nur, wie sie es entworfen.

Mein Stich auf das Problem (möglicherweise eine Implementierung Rube Goldberg) wäre es zu einem einzigen Login-Seite an der Wurzel von allen Clients gemeinsam umleiten zu lassen, sagen / Konto / Login. Diese Login-Seite würde alles nicht tatsächlich angezeigt werden; sie prüft entweder die ReturnUrl Parameter oder einen Wert I in der Sitzung oder ein Cookie haben, die den Client und verwendet, dass eine sofortige 302 Umleitung auf die spezifische / client / Konto / Login-Seite zur Ausgabe identifiziert. Es ist eine zusätzliche Umleitung, aber wahrscheinlich nicht erkennbar und es können Sie die in Umleitungsmechanismen gebaut verwenden.

Die andere Option ist Ihr eigenes benutzerdefiniertes Attribut zu erstellen, wie Sie etwas beschreiben und vermeiden, dass die RedirectToLoginPage() Methode auf der FormsAuthentication Klasse aufruft, da Sie es mit Ihrer eigenen Umleitungslogik ersetzt werden. (Sie können Ihre eigene Klasse zu erstellen, die ähnlich ist.) Da es sich um eine statische Klasse ist, bin ich keine Kenntnis von einem Mechanismus, mit dem Sie gerade Ihre eigene alternative Schnittstelle injizieren könnte und haben es funktionieren auf magische Weise mit der bestehenden [autorisieren] Attribut, das Schläge, aber Menschen vor ähnliche Dinge getan haben.

Ich hoffe, das hilft!

Andere Tipps

In der RTM-Version von ASP.NET MVC wird die Cancel-Eigenschaft fehlt. Dieser Code funktioniert mit 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:. Sie können die Standard-Formularauthentifizierung loginUrl in web.config deaktivieren - falls jemand vergisst man ein benutzerdefiniertes Attribut hat und nutzt die eingebaut [autorisiert] Attribut versehentlich

Ändern Sie den Wert in web.config:

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

Dann eine Aktion Methode ‚ERROR‘ machen, die einen Fehler meldet und leitet den Benutzer auf die allgemeinste Login-Seite haben.

Meine Lösung für dieses Problem war eine benutzerdefinierte ActionResult Klasse:

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

Dennoch, wenn man die integrierten ASP.NET FormsAuthentication zu verwenden entscheidet, kann man Application_AuthenticateRequest in Global.asax.cs overide wie folgt:

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;
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top