如何重定向到ASP中的動態登錄URL。NET MVC

[英]How to redirect to a dynamic login URL in ASP.NET MVC


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:

我正在創建一個為客戶端提供頁面的多租戶網站。URL的第一部分將是一個字符串,用於標識在全局中定義的客戶端。asax使用以下URL路由方案:

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

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

對於/foo/Home/Index這樣的url來說,這是可行的。

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.

然而,在使用[Authorize]屬性時,我希望重定向到同樣使用相同映射方案的登錄頁面。如果客戶端是foo,登錄頁面將是/foo/Account/ login,而不是web.config中定義的固定/Account/ login重定向。

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.

MVC使用HttpUnauthorizedResult返回401個未經授權的狀態,我猜想這可能導致ASP。NET重定向到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?

所以有人知道如何重寫ASP。網絡登錄重定向行為呢?還是通過創建自定義授權屬性來重定向MVC更好?

EDIT - Answer: after some digging into the .Net source, I decided that a custom authentication attribute is the best solution:

編輯-回答:在深入研究了。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 }
                });
        }
    }
}

3 个解决方案

#1


30  

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.

我認為主要的問題是,如果您要使用內置的ASP。NET FormsAuthentication類(沒有理由不這么做),最后會調用formsauthentic. redirecttologinpage(),它會查看一個已配置的URL。只有一個登錄URL,這就是他們設計的方式。

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.

我解決這個問題的方法(可能是Rube Goldberg實現)是讓它重定向到所有客戶機共享的根上的單個登錄頁面,例如/account/login。這個登錄頁面實際上不會顯示任何內容;它檢查ReturnUrl參數或會話中獲得的某個值或標識客戶端的cookie,並使用該屬性立即向特定/客戶端/帳戶/登錄頁面發送302重定向。這是一個額外的重定向,但可能不明顯,它允許您使用內置的重定向機制。

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.

另一個選項是在描述時創建您自己的自定義屬性,並避免調用FormsAuthentication類上的RedirectToLoginPage()方法,因為您將用自己的重定向邏輯替換它。(您可以創建類似的類。)因為它是一個靜態類,所以我不知道您可以通過什么機制注入您自己的替代接口,並讓它神奇地與現有的[授權]屬性一起工作,這是一種打擊,但是人們以前也做過類似的事情。

Hope that helps!

希望會有幫助!

#2


40  

In the RTM version of ASP.NET MVC, the Cancel property is missing. This code works with ASP.NET MVC RTM:

在RTM版本的ASP中。NET MVC,取消屬性缺失。這段代碼適用於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 }
                        });
            }
        }
    }
}

Edit: You may want to disable the default forms authentication loginUrl in web.config - in case somebody forgets you have a custom attribute and uses the built in [Authorize] attribute by mistake.

編輯:您可能想在web上禁用默認表單身份驗證登錄。配置——如果有人忘記了你有一個自定義屬性,並且錯誤地使用了[授權]屬性。

Modify the value in web.config:

修改web.config中的值:

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

Then make an action method 'ERROR' that logs an error and redirects the user to the most generic login page you have.

然后,創建一個記錄錯誤的操作方法“ERROR”,並將用戶重定向到您所擁有的最普通的登錄頁面。

#3


2  

My solution to this problem was a custom ActionResult class:

我對這個問題的解決方案是一個定制的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; }
    }

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2008/12/10/725c7fa68a0d590c31075c1fdae9f460.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com