如何redirect到ASP.NET MVC中的dynamicloginURL

我正在创build一个多租户网站,为客户提供页面托pipe服务。 URL的第一部分将是一个string,标识客户端,使用以下URL路由scheme在Global.asax中定义:

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

这工作正常,与/ foo / Home / Index的URL。

但是,当使用[Authorize]属性时,我想redirect到一个也使用相同映射scheme的login页面。 因此,如果客户端是foo,那么login页面将是/ foo / Account / Login,而不是web.config中定义的固定/帐户/loginredirect。

MVC使用HttpUnauthorizedResult返回401未授权状态,我认为这会导致ASP.NETredirect到web.config中定义的页面。

那么有谁知道如何重写ASP.NETloginredirect行为? 或者,通过创build一个自定义授权属性在MVC中redirect会更好吗?

编辑 – 答:一些挖掘到.Net源,我决定一个自定义的身份validation属性是最好的解决scheme:

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

我认为主要的问题是,如果你要搭载内置的ASP.NET FormsAuthentication类(没有什么好的理由你不应该这样做),那么在一天结束的时候会调用FormsAuthentication.RedirectToLoginPage()这将看看一个configuration的URL。 只有一个loginurl,而这正是他们devise的方式。

我试图解决这个问题(可能是Rube Goldberg的实现)就是让它redirect到所有客户端共享的根目录中的一个login页面,比如/ account / login。 这个login页面实际上不会显示任何东西; 它会检查ReturnUrl参数或者会话中的一些值,或者是一个标识客户端的cookie,并使用它来立即发送302到指定/客户端/帐户/login页面的redirect。 这是一个额外的redirect,但可能不明显,它可以让你使用内置的redirect机制。

另一种select是按照您所描述的方式创build您自己的自定义属性,并避免在FormsAuthentication类中调用RedirectToLoginPage()方法的任何内容,因为您将用自己的redirect逻辑来replace它。 (你可能会创build自己的类,因为它是一个静态类,我不知道任何机制,你可以注入自己的替代接口,并与现有的[Authorize]属性神奇地工作打击,但人们以前做过类似的事情 。

希望有所帮助!

在ASP.NET MVC的RTM版本中,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中的默认表单身份validationloginUrl – 以防有人忘记了您有一个自定义属性,并错误地使用内置[Authorize]属性。

修改web.config中的值:

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

然后制定一个操作方法“错误”,logging一个错误,并将用户redirect到您最常用的login页面。

我对这个问题的解决scheme是一个自定义的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; } }