如何重定向到ASP.NET MVC动态登录URL
-
21-08-2019 - |
题
我创建一个多租户网站,其中包含了客户端的网页。 URL的第一区段将是一个字符串,它识别客户端,使用下面的URL路由方案在Global.asax中定义:
"{client}/{controller}/{action}/{id}"
这个工作得很好,有URL如/富/主页/索引。
然而,使用[授权]属性时,我要重定向到也使用相同的映射方案的登录页面。因此,如果客户机是foo,登录页面将是/富/帐户/登录而不是在web.config中定义的固定/帐户/登录重定向。
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 }
});
}
}
}
解决方案
我认为主要的问题是,如果你要捎带上内置的ASP.NET FormsAuthentication类(有你不应该没有充分的理由),一些在这一天结束时要调用这是会看一个配置的URL FormsAuthentication.RedirectToLoginPage()
。这里只有一个登录网址,永远,那就是他们是如何设计的。
我在这个问题(可能是出自临时抱佛脚实现)刺会让它重定向到一个登录页面,在所有客户端共享的根,说/帐号/登录。这个登录页面实际上不会显示任何画面;它会检查无论是RETURNURL参数或一定的价值,我在会议上得到或可识别客户端,并使用该发出即时302重定向到具体/客户/帐号/登录页面的cookie。这是一个额外的重定向,但可能并不明显,它可以让你使用内置的重定向机制。
另一种选择是你描述和避免任何呼吁RedirectToLoginPage()
类FormsAuthentication
方法,因为你会用自己的重定向逻辑来取代它来创建自己的自定义属性。 (您可以创建自己的类类似。)由于它是一个静态类,我不知道的,你可能只是注入自己的替代接口的任何机制,并奇迹般地与现有的[授权]属性,工作当中打击,但人之前做过类似的事情。
希望帮助!
其他提示
在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中的默认窗体身份验证loginUrl - 万一有人忘记你有一个自定义属性,并使用内置的错误[授权]属性
在web.config中修改值:
<forms loginUrl="~/Account/ERROR" timeout="2880" />
然后制定行动方法“错误”是记录错误,并将用户重定向到您拥有最通用的登录页面。
我的对这个问题的解决方案是自定义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; }
}
不过,如果一个决定使用内置的ASP.NET FormsAuthentication,人们可以在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;
}
}
}