且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-10-18 19:19:44

我认为主要的问题是,如果你要捎带上内置的ASP.NET FormsAuthentication类(有没有很好的理由,你不应该 T),一些在这一天结束时会调用 FormsAuthentication.RedirectToLoginPage()这是要查找一个配置的URL。只有一个登录网址,永远,这就是他们是多么的设计吧。

我在这个问题(可能是一个鲁贝戈德堡实现)刺会让它重定向到一个登录页面,在所有客户端共享的根,说/帐号/登录。本登录页面实际上不会显示任何东西;它会检查无论是RETURNURL参数或值我有会话或标识客户端,并使用它来发布即时302重定向到具体/客户/帐号/登录页面的Cookie。这是一个额外的重定向,但可能并不明显,它可以让你使用内置的重定向机制。

另一种选择是,你描述和避免任何调用的 FormsAuthentication 的 RedirectToLoginPage()方法来创建自己的自定义属性code>类,因为你会用自己的重定向逻辑取代它。 (您可以创建自己的类类似)。因为它是一个静态类,我不知道通过它你可以只注入自己的另一种接口的机制,有它神奇地与现有的[授权]属性,工作这打击,但以前做过类似的事情。

希望帮助!

I'm creating a multi-tenancy web site which hosts pages for clients. The first segment of the URL will be a string which identifies the client, defined in Global.asax using the following URL routing scheme:

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

This works fine, with URLs such as /foo/Home/Index.

However, when using the [Authorize] attribute, I want to redirect to a login page which also uses the same mapping scheme. So if the client is foo, the login page would be /foo/Account/Login instead of the fixed /Account/Login redirect defined in web.config.

MVC uses an HttpUnauthorizedResult to return a 401 unauthorised status, which I presume causes ASP.NET to redirect to the page defined in web.config.

So does anyone know either how to override the ASP.NET login redirect behaviour? Or would it be better to redirect in MVC by creating a custom authorization attribute?

EDIT - Answer: after some digging into the .Net source, I decided that a custom authentication attribute is the best 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 }
                });
        }
    }
}

I think the main issue is that if you're going to piggyback on the built-in ASP.NET FormsAuthentication class (and there's no good reason you shouldn't), something at the end of the day is going to call FormsAuthentication.RedirectToLoginPage() which is going to look at the one configured URL. There's only one login URL, ever, and that's just how they designed it.

My stab at the problem (possibly a Rube Goldberg implementation) would be to let it redirect to a single login page at the root shared by all clients, say /account/login. This login page wouldn't actually display anything; it inspects either the ReturnUrl parameter or some value I've got in the session or a cookie that identifies the client and uses that to issue an immediate 302 redirect to the specific /client/account/login page. It's an extra redirect, but likely not noticeable and it lets you use the built in redirection mechanisms.

The other option is to create your own custom attribute as you describe and avoid anything that calls the RedirectToLoginPage() method on the FormsAuthentication class, since you'll be replacing it with your own redirection logic. (You might create your own class that is similar.) Since it's a static class, I'm not aware of any mechanism by which you could just inject your own alternative interface and have it magically work with the existing [Authorize] attribute, which blows, but people have done similar things before.

Hope that helps!