如何在 ASP.NET MVC 中重定向到動態登錄 URL
我正在創建一個為客戶託管頁面的多租戶網站。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" />然後創建一個操作方法“錯誤”,記錄錯誤並將使用者重定向到您擁有的最通用的登錄頁面。