MVC 5 Comment définir Owin LoginPath avec des routes localisées

J’ai un site Web MVC 5 avec des routes localisées définies comme

routes.MapRoute( name: "Default", url: "{culture}/{controller}/{action}/{id}", defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional } ); 

Où la culture par défaut donne "en-US" .


Le problème se pose au démarrage, je dois définir l’URL de connexion en utilisant la propriété LoginPath, qui est définie une fois et il utilisera toujours la valeur fournie, par exemple la culture par défaut si “/ en-Us / Account / Login” est la valeur spécifiée . J’ai ensuite essayé d’utiliser la classe UrlHelper dans l’espoir d’une expérience magique mais le résultat est évidemment le même:

 var httpContext = HttpContext.Current; if (httpContext == null) { var request = new HttpRequest("/", "http://example.com", ""); var response = new HttpResponse(new SsortingngWriter()); httpContext = new HttpContext(request, response); } var httpContextBase = new HttpContextWrapper(httpContext); var routeData = new RouteData(); var requestContext = new RequestContext(httpContextBase, routeData); UrlHelper helper = new UrlHelper(requestContext); var loginPath = helper.Action("Login", "Account"); // Enable the application to use a cookie to store information for the signed in user app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathSsortingng(loginPath) }); 

Ma question est la suivante: existe-t-il un moyen de pirater ce mécanisme pour récupérer dynamicment la culture actuelle ou suis-je obligé de définir la culture actuelle dans un cookie et lorsque je suis redirigé vers la page de connexion culture avant de rendre la page?

Merci

J’ai exactement le même problème et j’ai trouvé un moyen de surmonter cette limitation.

Dans les options CookieAuthenticationOptions , il existe une propriété “Provider” qui est initialisée avec le CookieAuthenticationProvider. Cela implémente une méthode appelée ApplyRedirect et un délégué OnApplyRedirect . Ma première idée était d’écraser ce ApplyRedirect et d’implémenter la logique requirejse pour gérer les routes localisées. Mais malheureusement, il ne peut pas être dépassé. Passer ma logique à OnApplyRedirect provoque le remplacement du comportement par défaut. En théorie, vous pouvez saisir la source de ce comportement , le copier dans votre projet et le modifier selon vos besoins, mais ce n’est évidemment pas une bonne pratique. Tout d’abord, j’ai décidé de créer un wrapper autour du CookieAuthenticationProvider avec deux points d’extension utilisant des delegates et de conserver le comportement par défaut, à l’exception de l’URL utilisée – ou de contourner le wrapper (thx to lafi).

Ensuite, dans la configuration d’authentification, j’ai ajouté ma logique personnalisée au fournisseur:

 public void ConfigureAuth(IAppBuilder app) { UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext); CookieAuthenticationProvider provider = new CookieAuthenticationProvider(); var originalHandler = provider.OnApplyRedirect; //Our logic to dynamically modify the path (maybe needs some fine tuning) provider.OnApplyRedirect = context => { var mvcContext = new HttpContextWrapper(HttpContext.Current); var routeData = RouteTable.Routes.GetRouteData(mvcContext); //Get the current language RouteValueDictionary routeValues = new RouteValueDictionary(); routeValues.Add("lang", routeData.Values["lang"]); //Reuse the RetrunUrl Uri uri = new Uri(context.RedirectUri); ssortingng returnUrl = HttpUtility.ParseQuerySsortingng(uri.Query)[context.Options.ReturnUrlParameter]; routeValues.Add(context.Options.ReturnUrlParameter, returnUrl); //Overwrite the redirection uri context.RedirectUri = url.Action("login", "account", routeValues); originalHandler.Invoke(context); }; app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathSsortingng(url.Action("login", "account")), //Set the Provider Provider = provider }); } 

Voir aussi ce code:

  • CookieAuthenticationHandler
  • CookieAuthenticationProvider

J’espère que cela correspond à vos besoins.

MISE À JOUR: Pour moins de confusion, j’ai mis à jour ma réponse pour utiliser l’amélioration de @Lafis, sans utiliser de classe wrapper pour appliquer le comportement étendu. S’il vous plait, donnez aussi crédit à @Lafis quand vous votez.

Pour améliorer la réponse à @martinoss, vous pouvez atteindre le même résultat sans implémenter de wrapper. Copiez simplement le gestionnaire d’origine, affectez-en un nouveau qui implémente votre logique de redirection pour modifier context.RedirectionUri et, à la fin, appelez le gestionnaire d’origine.

 CookieAuthenticationProvider provider = new CookieAuthenticationProvider(); var originalHandler = provider.OnApplyRedirect; provider.OnApplyRedirect = context => { //insert your logic here to generate the redirection URI ssortingng NewURI = "...."; //Overwrite the redirection uri context.RedirectUri = NewURI; originalHandler.Invoke(context); }; app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathSsortingng(url.Action("Login", "Account")), Provider = provider }); 

Que dis-tu de ça:

 var cao = new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathSsortingng("/Account/Login"), Provider = new CookieAuthenticationProvider { OnApplyRedirect = ApplyRedirect } }; app.UseCookieAuthentication(cao); 

et

  private static void ApplyRedirect(CookieApplyRedirectContext context) { UrlHelper _url = new UrlHelper(HttpContext.Current.Request.RequestContext); Ssortingng actionUri = _url.Action("Login", "Account", new { }); context.Response.Redirect(actionUri); } 

Sans prendre trop de responsabilités au format URL, vous pouvez faire quelque chose comme ceci

 public static void Configuration(IAppBuilder app) { UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathSsortingng(url.Action("LogOn", "Account", new { area = "Account" })), Provider = new CookieAuthenticationProvider { OnApplyRedirect = context => context.Response.Redirect(context.RedirectUri.Replace(CultureHelper.GetDefaultCulture(), Thread.CurrentUiCulture.Name)) } }); } 

J’ai amélioré la réponse de Sentinel pour conserver l’URL de retour:

 private static void ApplyRedirect(CookieApplyRedirectContext context) { //use this way to keep return url var loginUrl = context.RedirectUri.Insert( context.RedirectUri.IndexOf("/Account/Login"), "/" + CultureHelper.GetCurrentCulture()); context.Response.Redirect(loginUrl); } 

Je pense que j’ai un an de retard dans cette réponse mais l’objective principal ici est de partager les connaissances … 🙂

Je viens de trouver le même problème dans une application que je développe actuellement. J’ai regardé la quantité de code dont nous avions besoin (dans les messages précédents) pour résoudre ce problème et je m’inquiète (la plupart du code était complexe et touchait l’intérieur de la bête). J’ai donc essayé de trouver une solution plus simple et ce que j’ai fait a été d’append l’itinéraire suivant à ma collection d’itinéraires:

 routes.MapRoute( name: "loginRoute", url: "account/login", defaults:new { culture = "", controller = "account", action = "login", id = UrlParameter.Optional }); 

Cela permettra à mon action de connexion dans le contrôleur de compte d’être appelée et mon mécanisme standard (une substitution à la méthode BeginExecuteCore à partir de Controller) est capable d’attacher la culture d’interface utilisateur actuelle à l’URL.

J’espère que ça aide quelqu’un.

Ajouté: Mon mécanisme standard:

 protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) { var cultureName = RouteData.Values["culture"] as ssortingng; var cultureCookie = Request.Cookies["_culture"]; if (cultureCookie != null && ssortingng.IsNullOrEmpty(cultureName)) { cultureName = cultureCookie.Value; } if (cultureName == null) cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : null; cultureName = CultureHelper.GetImplementedCulture(cultureName); if (RouteData.Values["culture"] as ssortingng != cultureName) { RouteData.Values["culture"] = cultureName.ToLowerInvariant(); // lower case too var cookie = Request.Cookies["_culture"]; if (cookie != null) cookie.Value = cultureName; // update cookie value else { cookie = new HttpCookie("_culture") { Value = cultureName, Expires = DateTime.Now.AddYears(1) }; } Response.Cookies.Add(cookie); // Redirect user Response.RedirectToRoute(RouteData.Values); } Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; return base.BeginExecuteCore(callback, state); } 

J’ai trouvé beaucoup plus facile:

 UrlHelper _url = new UrlHelper(HttpContext.Current.Request.RequestContext); public void ConfigureAuth(IAppBuilder app) { Ssortingng actionUri = _url.Action("Login", "Account", new { }); Ssortingng unescapeActionUri = System.Uri.UnescapeDataSsortingng(actionUri); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathSsortingng(unescapeActionUri) }); [...]