實務上,在一個ASP.NET MVC系統中,使用者第一個接觸到的介面往往就是登入介面。
登入系統確認使用者身分後,系統的工作才正要開始。確認使用者有權限可以進入系統,便需要在Control的每個Action中去確認,該使用者是否有權限進入這個功能項目,例如在系統中有一個建立基本資料的 BasicDataController
public class BasicDataController : Controller { // 產品列表 public ActionResult ProductList { // 如果不是合法的使用者,轉回登入頁面 if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); // 產品列表的程式碼…. return new View(); } // 新增產品 public ActionResult CreateProduct { // 如果不是合法的使用者,轉回登入頁面 if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); // 新增產品的程式碼…. return new View(); } // 編輯產品 public ActionResult EditProduct { // 如果不是合法的使用者,轉回登入頁面 if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); // 編輯產品的程式碼…. return new View(); }
幾乎在每個Action上都要做相同的事情
// 如果不是合法的使用者,轉回登入頁面 if (!Request.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage();
這樣子的系統,除了要重複相當多的程式碼外,當權限管理更複雜時(要依使用者身分來區別是否可以進入該功能)程式會變得難以維護。利用MVC一個相當方便的功能Authorization Filters,可以解決這個問題。(在此要提醒,安全性機制要考量的問題相當廣,只是單純將程式複製貼上,或可以解決眼前的問題,但是當系統放上真實世界的網路時,面對各種安全性漏洞,必須做更嚴密的測試,在這裡僅就ASP.NET MVC專案中的 Authorization Filters做討論,至於資訊安全問題是另一個層次的議題了,在此不就這個問題討論)
建立一個MVC專案
新增HomeController
加入Index, ProductList, ProductCreate, ProductEdit, ProductDelete等5個Action以及View
Index.cshtml
ProductList.cshtml
ProductAdd.cshtml
ProductEdit.cshtml
ProductDelete.cshtml
新增一個Infrastructure資料夾,並且在Infrustrator中加入CustomAuthAttribute類別
注意:請以Attribute做為結尾。
CustomAuthAttribut.cs內容如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Inventory.Infrastructure { public class CustomAuthAttribute:AuthorizeAttribute { private string _authstr; public CustomAuthAttribute(string attrib) { _authstr = attrib; } protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext.Request.IsLocal) return _authstr=="YES"; else return true; } } }
1.加入命名空間 System.Web.Mvc
using System.Web.Mvc;
2.繼承AuthorizeAttribute
namespace Inventory.Infrastructure { public class CustomAuthAttribute:AuthorizeAttribute {
參數由建構函式傳遞至Filter內,覆載AuthorizeCore驗證不通過時擲出意外
private string _authstr; public CustomAuthAttribute(string attrib) { _authstr = attrib; } protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext.Request.IsLocal) return _authstr=="YES"; else return true; }
再回到HomeController中
using Inventory.Infrastructure; .... [CustomAuth("YES")] public ActionResult ProductList() { return View(); } [CustomAuth("NO")] public ActionResult ProductAdd() { return View(); } [CustomAuth("NO")] public ActionResult ProductEdit() { return View(); } [CustomAuth("NO")] public ActionResult ProductDelete() { return View(); }
3.加入Inventory..Infrastructure命名空間(撰寫Filter的資料夾)
using Inventory.Infrastructure;
4.在要驗證的Action前面加上Attribute
[CustomAuth("YES")] public ActionResult ProductList() { return View(); } [CustomAuth("NO")] public ActionResult ProductAdd() { return View(); }
[CustomAuth(“YES”)]會將”YES”由new CustomAuthAttribute(“Yes”)傳遞至建構函式中,藉由AuthorizeCore方法驗證,當回傳false時,則會擲出意外。
以下示範:
按下產品列表
[CustomAuth("YES")] public ActionResult ProductList()
點選新增產品
[CustomAuth("NO")] public ActionResult ProducAdd()
產生401(沒有權限)的錯誤
再回到CustomAuthAttribute.cs中加入
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { filterContext.Result = new RedirectResult("/Home/Index"); }
將錯誤的頁面轉到 Home/Index(或是Login)即可完成這部份的自定驗證權限工作。
您可在下列課程中了解更多技巧喔!
相關學習資源
【MVC52CS】使用ASP.NET MVC 5設計網站應用程式-Visual C# 2015