ASP.Net MVC 基於安全性隱藏/顯示菜單項
我正在開發一個 ASP.Net MVC 3 站點。_Layout 主視圖包含一個菜單,我想根據您是否登錄以及您所處的角色隱藏菜單中的一些項目。
這目前使用這樣的程式碼
@if (HttpContext.Current.User.Identity.IsAuthenticated) { <li id="MyLearningTab">@Html.ActionLink("My Learning", "MyLearning", "Learning")</li> if (HttpContext.Current.User.IsInRole("Reporters")) { <li id="ReportTab">@Html.ActionLink("Reports", "Index", "Reports")</li> } if (HttpContext.Current.User.IsInRole("Administrators")) { <li id="DashboardTab">@Html.ActionLink("Dashboard", "Dashboard", "Admin")</li> <li id="AdminTab">@Html.ActionLink("Admin", "Index", "Admin")</li> } }我想將其重構為更具可讀性並提出類似的東西
@if ((bool)ViewData["MenuMyLearning"]){<li id="MyLearningTab">@Html.ActionLink("My Learning", "MyLearning", "Learning")</li> } @if((bool)ViewData["MenuReports"]){<li id="ReportTab">@Html.ActionLink("Reports", "Index", "Reports")</li>} @if ((bool)ViewData["MenuDashboard"]){<li id="DashboardTab">@Html.ActionLink("Dashboard", "Dashboard", "Admin")</li>} @if ((bool)ViewData["MenuAdmin"]){<li id="AdminTab">@Html.ActionLink("Admin", "Index", "Admin")</li>}我最初將以下內容添加到我的基本控制器建構子中,認為我可以在那里為這些屬性設置 ViewData
ViewData["MenuDashboard"] = User != null && User.Identity.IsAuthenticated && User.IsInRole("Administrators"); ViewData["MenuAdmin"] = User != null && User.Identity.IsAuthenticated && User.IsInRole("Administrators"); ViewData["MenuReports"] = User != null && User.Identity.IsAuthenticated && User.IsInRole("Reportors"); ViewData["MenuMyLearning"] = User != null && User.Identity.IsAuthenticated;然而事實證明,在生命週期的這一點上,使用者對象為空。我也嘗試過創建一個自定義全域過濾器,但 ViewData 是不可訪問的。
做這樣的事情的推薦方法是什麼?我是否應該將視圖中的所有 HttpContext 程式碼保持原樣?
這就是我最終要做的。我為每個菜單項創建了一個名為 MenuSecurity 的幫助程序類,該類具有靜態布爾屬性,顯示哪些項應該可見。每個屬性看起來像這樣
public static bool DashboardVisible { get { return HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated; } }然後我整理了我的菜單部分視圖,看起來像這樣
@if (MenuSecurity.ReportsVisible){<li id="ReportTab">@Html.ActionLink("Reports", "Index", "Reports")</li>} @if (MenuSecurity.DashboardVisible){<li id="DashboardTab">@Html.ActionLink("Dashboard", "Dashboard", "Admin")</li>} @if (MenuSecurity.AdminVisible){<li id="AdminTab">@Html.ActionLink("Admin", "Index", "Admin")</li>}
關於角色的一般建議
我這樣做的方法是創建一個自定義主體並在其中儲存額外的必需資訊。在您的範例中,這至少包括使用者的角色。這樣您就可以避免對使用者儲存(可能是 SQL 數據庫)進行大量額外的訪問。
看看我的這個問題,我在其中給出了我成功使用的程式碼:Base Controller ASP.NET MVC 3 中的這個自定義主體是否非常低效?
請注意,我將自定義主體儲存在記憶體中而不是會話中(只是對會話劫持感到偏執)。
我喜歡這種方法,因為它非常可擴展。例如,我已經對此進行了擴展,以便在使用者通過 Facebook 登錄時公開 Facebook 憑據。
請記住,如果您正在記憶體數據,則需要記住在數據更改時對其進行更新!
回答你的問題
只是補充一點,在您的特定情況下,您可能應該將這些額外資訊儲存在 a 中
ViewModel,然後您的視圖會說:@if(ShowReports) { <li id="ReportTab">@Html.ActionLink("Reports", "Index", "Reports")</li> } @if(ShowDashboard) { <li id="DashboardTab">@Html.ActionLink("Dashboard", "Dashboard", "Admin")</li> } @if(ShowAdmin { <li id="AdminTab">@Html.ActionLink("Admin", "Index", "Admin")</li> }使用 ViewModel 程式碼說如下:
public bool ShowReports {get;set;} public bool ShowDashboard {get;set;} public bool ShowAdmin {get;set;} public void SetViewModel() { if (User.Identity.IsAuthenticated) { if (HttpContext.Current.User.IsInRole("Reporters")) { ShowReports = true; } if (HttpContext.Current.User.IsInRole("Administrators")) { ShowDashboard = true; ShowAdmin = true; } } }實際上,我傾向於更進一步,並
ReportsLink在我的文件中創建一個ViewModel並將其設置為如果使用者被授權則包含連結,或者如果他們不是,則設置為空字元串。然後視圖只是說:@Model.ReportsLink @Model.DashboardLink @Model.AdminLink在這種情況下,ViewModel 的相關部分可能是這樣的:
ReportLink = new MvcHtmlString(HtmlHelper.GenerateLink(HttpContext.Current.Request.RequestContext, System.Web.Routing.RouteTable.Routes, "linktext", "routename", "actionname", "controllername", null, null));