如何重定向到ASP.NET MVC动态登录URL

问题描述 投票:93回答:4

我创建一个多租户网站,其中包含了客户端的网页。的URL的第一段将其识别所述客户端,使用下面的URL路由方案在Global.asax中定义的字符串:

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

这工作得很好,用的URL如/富/首页/索引。

但是,使用[授权]属性的时候,我想重定向到也使用相同的映射方案的登录页面。因此,如果客户端是foo,那么登录页面会/富/帐号/登录,而不是在web.config中定义的固定/帐号/登录重定向。

MVC使用的HttpUnauthorizedResult返回一个401种Unauthorized状态,这我相信会导致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 }
                });
        }
    }
}
.net asp.net-mvc authentication forms-authentication asp.net-routing
4个回答
30
投票

我认为主要的问题是,如果你要捎带上内置的ASP.NET FormsAuthentication类(有你不应该没有充分的理由),在一天结束的东西会调用FormsAuthentication.RedirectToLoginPage()这是去看看一个配置的URL。这里只有一个登录网址,永远,那就是他们是如何设计的。

我在这个问题(可能是出自临时抱佛脚实现)刺会让它重定向到一个登录页面,在所有客户端共享的根,说/帐号/登录。这个登录页面实际上不会显示任何画面;它会检查无论是RETURNURL参数或一定的价值,我在会议上得到或可识别客户端,并使用该发出即时302重定向到具体/客户/帐号/登录页面的cookie。这是一个额外的重定向,但可能并不明显,它可以让你使用内置的重定向机制。

另一种选择是你描述和避免任何呼吁RedirectToLoginPage()FormsAuthentication方法,因为你会用自己的重定向逻辑来取代它来创建自己的自定义属性。 (您可以创建自己的类类似。)由于它是一个静态类,我不知道的,你可能只是注入自己的替代接口的任何机制,并奇迹般地与现有的[授权]属性,工作当中打击,但people have done similar things before

希望帮助!


40
投票

在ASP.NET MVC的RTM版本中,取消财产丢失。该代码可以使用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" />

然后制定行动方法“错误”,它记录错误,用户必须是最通用的登录页面重定向。


2
投票

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

0
投票

不过,如果你已经决定使用内置的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;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.