Dot-Net

如何在 ASP.NET MVC 中重定向到動態登錄 URL

  • December 10, 2008

我正在創建一個為客戶託管頁面的多租戶網站。URL 的第一段將是一個標識客戶端的字元串,在 Global.asax 中使用以下 URL 路由方案定義:

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

這可以正常工作,使用 /foo/Home/Index 等 URL。

但是,當使用 [Authorize] 屬性時,我想重定向到也使用相同映射方案的登錄頁面。因此,如果客戶端是 foo,則登錄頁面將是 /foo/Account/Login 而不是 web.config 中定義的固定 /Account/Login 重定向。

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 類(並且沒有充分的理由不應該這樣做),那麼一天結束時就會FormsAuthentication.RedirectToLoginPage()呼叫查看一個配置的 URL。永遠只有一個登錄 URL,這就是他們設計的方式。

我對這個問題(可能是 Rube Goldberg 實現)的嘗試是讓它重定向到所有客戶端共享的根目錄中的單個登錄頁面,例如 /account/login。這個登錄頁面實際上不會顯示任何內容;它檢查 ReturnUrl 參數或我在會話中獲得的某個值或標識客戶端的 cookie,並使用它來發出立即 302 重定向到特定的 /client/account/login 頁面。這是一個額外的重定向,但可能不會引人注意,它允許您使用內置的重定向機制。

另一種選擇是在描述時創建自己的自定義屬性,並避免呼叫類RedirectToLoginPage()上的方法的任何內容FormsAuthentication,因為您將用自己的重定向邏輯替換它。(您可以創建自己的類似類。)由於它是一個靜態類,我不知道有任何機制可以注入您自己的替代介面並讓它與現有的 [Authorize] 屬性一起神奇地工作,它打擊,但人們以前也做過類似的事情

希望有幫助!

在 RTM 版本的 ASP.NET MVC 中,缺少 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 - 以防有人忘記您有自定義屬性並錯誤地使用了內置的 [Authorize] 屬性。

修改 web.config 中的值:

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

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

引用自:https://stackoverflow.com/questions/356982