.Net MVC實現角色-API權限驗證的一種方式


閱文時長 | 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) 分析思路

  1. 首先對"Role-API"的對應關系進行梳理,一般用一張關系表進行存儲。存儲在緩存中。(緩存寫入節點、過期時間按需而論),比如:博主是在項目啟動的Global.asax文件中寫入緩存,設置為永不過期,理由是項目功能已基本不迭代(當然這也有很多不便之處:例如如果按博主的這種方式,如果寄托於IIS,需要Stop后Start來更新緩存)。
  2. 新增一個特性AjaxAuthorizeAttribute繼承於身份驗證AuthorizeAttribute特性,重寫OnAuthorization方法;寫入邏輯為:用服務器端存儲的當前用戶的上下文信息中的Role取其可訪問的API集合,再與訪問接口的URL做判斷,判斷此Role是否具備該接口的權限,若不具備權限則返回403.cshtml的靜態頁;此特性用來標記需驗證的控制器或Action。
  3. 以上這一種方式即可簡單且相對可靠的實現對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即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM