實務上,在一個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