95 votes

Comment faire pour rediriger vers une URL de connexion dynamique dans ASP.NET MVC

Je suis de la création d'un multi-tenancy site web qui héberge des pages pour les clients. Le premier segment de l'URL sera une chaîne de caractères qui identifie le client, défini dans le Mondial.asax à l'aide de l'URL suivante schéma de routage:

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

Cela fonctionne bien, avec des Url de la forme /toto/Home/Index.

Cependant, lors de l'utilisation de l'attribut [Authorize], je veux rediriger vers une page de connexion qui utilise le même schéma de mise en correspondance. Ainsi, si le client est toto, la page de connexion /foo/Compte/Login à la place de l'fixe /Compte/Login redirect défini dans le web.config.

MVC utilise un HttpUnauthorizedResult de retour 401 non autorisé d'état, dont je présume que les causes ASP.NET pour rediriger vers la page définie dans le web.config.

Donc, personne ne sait non plus comment remplacer la ASP.NET login redirect comportement? Ou serait-il mieux de rediriger MVC par la création d'une coutume de l'autorisation de l'attribut?

EDIT Réponse: après quelques recherches dans le .Net de source, j'ai décidé qu'une authentification personnalisée attribut est la meilleure solution:

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

40voto

user134936 Points 11

Dans la version RTM de ASP.NET MVC, la propriété Cancel est manquant. Ce code fonctionne avec 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: Vous souhaiterez peut-être désactiver par défaut l'authentification par formulaires loginUrl dans le web.config - dans le cas où quelqu'un oublie qui vous ont un attribut personnalisé et utilise le construit dans l'attribut [Authorize] par erreur.

Modifier la valeur dans le web.config:

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

Procéder ensuite à une méthode d'action "ERREUR" qui enregistre une erreur et redirige l'utilisateur vers le plus générique de la page de login que vous avez.

30voto

Nicholas Piasecki Points 13681

Je pense que le principal problème est que si vous allez à se greffer sur le haut-ASP.NET classe FormsAuthentication (et il n'y a aucune bonne raison pour laquelle vous ne devriez pas), quelque chose à la fin de la journée est d'aller en appel d' FormsAuthentication.RedirectToLoginPage() qui va regarder configuré URL. Il n'y a qu'une URL de connexion, jamais, et c'est juste la façon dont ils ont conçu.

Mon coup de poignard dans le problème (peut-être un Rube Goldberg mise en œuvre) serait de le laisser rediriger vers une seule page de connexion à la racine partagé par tous les clients, par exemple /compte/login. Cette page de connexion ne fait pas afficher quoi que ce soit; il inspecte le ReturnUrl paramètre ou une valeur que j'ai obtenu à la session ou un cookie qui identifie le client et l'utilise pour émettre immédiatement un redirection 302 vers le spécifique /client/compte/login page. Il s'agit d'un supplément de redirection, mais probablement pas perceptible, et elle permet d'utiliser le construit dans la redirection des mécanismes.

L'autre option est de créer votre propre attribut personnalisé comme vous le décrivez et éviter tout ce que les appels de l' RedirectToLoginPage() méthode sur l' FormsAuthentication de la classe, puisque vous serez en remplacement avec la redirection de votre propre logique. (Vous pouvez créer votre propre classe qui est similaire). Puisque c'est une classe statique, je ne suis pas au courant de tout mécanisme par lequel vous pouvez simplement injecter votre propre interface de rechange et ont la magie de travail avec l'attribut [Authorize], qui souffle, mais les gens ont fait des choses similaires avant.

Espérons que ça aide!

2voto

Kieron Points 10261

Ma solution à ce problème était une coutume `` classe :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X