閱文時長 | 1.15分鐘 字數統計 | 1844.8字元 主要內容 | 1、引言&背景 2、部分設計分享 3、聲明與參考資料 『.Net MVC實現角色-API許可權驗證的一種方式』 編寫人 | SCscHero 編寫時間 | 2022/3/27 PM9:31 文章類型 | 系列 完成度 | 已完成 ...
閱文時長 | | 1.15分鐘 | 字數統計 | | 1844.8字元 |
主要內容 | | 1、引言&背景 2、部分設計分享 3、聲明與參考資料 | ||
『.Net MVC實現角色-API許可權驗證的一種方式』 | |||
編寫人 | | SCscHero | 編寫時間 | | 2022/3/27 PM9:31 |
文章類型 | | 系列 | 完成度 | | 已完成 |
座右銘 | 每一個偉大的事業,都有一個微不足道的開始。 |
一、引言&背景 完成度:100%
a) 應對問題&背景
RBAC的許可權設計已經應用到越來越多的系統中,然而在一些老項目中,對各個Role可訪問的API並未做相關的限制,從而引發高級別的安全漏洞。這裡介紹一種簡單且比較可靠的設計。
b) 應用場景
- 在RBAC的許可權設計中,對應的Role進行API許可權檢驗。
c) 分析思路
- 首先對"Role-API"的對應關係進行梳理,一般用一張關係表進行存儲。存儲在緩存中。(緩存寫入節點、過期時間按需而論),比如:博主是在項目啟動的Global.asax文件中寫入緩存,設置為永不過期,理由是項目功能已基本不迭代(當然這也有很多不便之處:例如如果按博主的這種方式,如果寄托於IIS,需要Stop後Start來更新緩存)。
- 新增一個特性AjaxAuthorizeAttribute繼承於身份驗證AuthorizeAttribute特性,重寫OnAuthorization方法;寫入邏輯為:用伺服器端存儲的當前用戶的上下文信息中的Role取其可訪問的API集合,再與訪問介面的URL做判斷,判斷此Role是否具備該介面的許可權,若不具備許可權則返回403.cshtml的靜態頁;此特性用來標記需驗證的控制器或Action。
- 以上這一種方式即可簡單且相對可靠的實現對RBAC許可權設計中,Role-API的許可權校驗。
二、部分設計分享 完成度:100%
a) Role-API存儲關係表
以下是存儲"Role-API"對應關係的關係表,如圖博主是用了五個欄位來存:步長為10主鍵ID、RoleID、RoleName、Url、APiDesc。其中RoleName和ApiDesc是冗餘欄位,方便開發者閱讀設計的,在緩存中存的對象不需要存RoleName和ApiDesc。
其中有一點需要註意的是URL,一般都是維護成/Area/Controller/Action。
b) AjaxAuthorizeAttribute
AjaxAuthorizeAttribute是自定義的重寫身份驗證特性的類。以下為一個通用設計。其中需要註意的是第2步驟,在取AuthorizationContext中的請求路由時,有幾種取數方式,註意區別。在以下代碼示例中有一些解釋可以參考。
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
//1. 從緩存中取數據的Obj對象,並將Obj轉換為實體對象。(轉換方式是否最優有待思考優化,先不做討論)
IList objList = (IList)CacheDataLogic.CacheHelper.GetData(ParameterNames.CacheRoleResourceAll);
var res = objList.Cast<MMC_RoleResourceMap>();
//ApplicationContext是我們封裝的取用戶上下文的類
var RoleName = ((RoleModel)CacheDataLogic.CacheHelper.GetData(ParameterNames.CacheClientUserRole + ApplicationContext.Current.LoginUserInfo.UserModel.UserID)).RoleName;
//2. 取當前用戶API集合是否包含請求集合。
//filterContext.HttpContext.Request.RawUrl//路由後帶參數,取到的數據是帶參數的。比如:/SCscCon/SCscAction?scsc=6666。
//filterContext.HttpContext.Request.Path//可以過濾掉?後的參數,比如:/Claim/SCscAction /?scsc=4430。但無法解決不帶?的參數URL。比如: /Claim/ClaimApply/4430
var spA = filterContext.HttpContext.Request.Path.Split('/');//如果上一種不是想用來判斷的參數,可以做截取。比如下麵這樣。
//3. 判斷當前用戶API集合是否包含請求集合。
if (res.Where(o => o.RoleName == RoleName && o.Url == ("/" + spA[1] + "/" + spA[2])).Count() > 0)
{
base.OnAuthorization(filterContext);
}
else
{
HttpContext.Current.Response.Redirect("~/AuthorizeError.html");
return;
}
}
}
另外建議大家可以瞭解一下AuthorizeAttribute對象,其中的各方法的調用順序可以研究研究,比如HandleUnauthorizedRequest方法等等,都是需要掌握的知識點。
c) 非授權通用頁
用來重定向的通用頁html代碼,記錄一下,後面方便復用。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<hgroup>
<h1>Error.</h1>
<h2>An error occurred while processing your request.</h2>
</hgroup>
</body>
</html>
三、聲明與參考資料 完成度:100%
原創博文,未經許可請勿轉載。
如有幫助,歡迎點贊、收藏、關註。如有問題,請評論留言!如需與博主聯繫的,直接博客私信SCscHero即可。