日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RBAC的资料

發布時間:2023/12/15 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RBAC的资料 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

利用?AOP?實現?.NET?上完整的基于角色的訪問控制(RBAC)模型?

一. 背景

  • .NET 平臺上沒有完整的 RBAC 機制,.NET 中的安全模型(代碼訪問安全性:CAS)只是實現到 Role 層次,沒有細化到 Task 層次,ASP.NET 2.0 中的諸多安全機制,如 Membership、Web.Config 的安全配置,都只能針對 Role 進行設置,大家在利用這些安全機制,往往需要在程序/代碼硬編碼(HardCode)角色,這樣就無法實現在運行期自定義角色的功能
  • Windows 2000/2003 中自帶的 Authorization Manager 雖然實現了較為完整的RBAC模型,但一般只適用于 Windows 用戶,而且也需要手動去進行權限檢查(調用 AccessCheck方法)
  • 權限檢查是一個通用操作,最好的實現方式就是面向方面的編程(AOP)
  • 二、相關主題介紹

  • RBAC模型的要素:三個實體:用戶、角色、任務(或操作)(User、Role、Task),其穩定性逐漸增強,兩個關系,User<->Role、Role<->Task,其中:
    • User 是日常管理運行時建立
    • Role 是部署/交付建立
    • Task 是開發時確定
    • User<->Role 是日常管理運行時建立
    • Role<->Task 是部署/交付時建立
  • 一般來說,Task是固定的,是和應用程序緊密綁定的,即使對之進行硬編碼,也沒有關系
  • User/Role 部分比較容易實現,例如ASP.NET 2.0中 Membership 的實現
  • 三、具體實現

    注:本文中實現 AOP 的思路主要來自于如下文章:Aspect oriented Programming using .NET - AOP in C# (http://www.developerfusion.co.uk/show/5307/3/) ,這是我看到的、在.NET 上實現 AOP最簡捷/方便的方法,它不便提供了原理介紹,也提供了 Visual Studio 2005 的 Sample Project ,其中有 Security Check 和 Logging 的 AOP 功能。它的優點在于,在實現 AOP 的同時,不需要再去建立接口(這是很多人的做法),直接在原有類上進行少量改動,即可實現完整的 AOP 功能。

    1. 定義描述“Task”(任務)的 Attribute

    using System; namespace BusinessLogic.Security ...{ /**//// /// 用于定義系統中的操作 /// [AttributeUsage(AttributeTargets.All,AllowMultiple=false,Inherited=true)] public sealed class Task : Attribute ...{ private string _name,_description; public string Name ...{ get ...{ return _name; } set ...{ _name = value; }} public string Description ...{ get ...{ return _description; } set ...{ _description = value; }} public Task(string name,string description) ...{_name = name;_description = description;} public Task() ...{}} }

    2. 編寫權限檢查的 AOP 類 SecurityAspect,完成權限檢查的功能

    using System; using System.Diagnostics; using System.Reflection; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Activation; namespace BusinessLogic.Security ...{ //消息接收器 internal class SecurityAspect : IMessageSink ...{ //內部變量 private IMessageSink m_next; //構造方法 internal SecurityAspect(IMessageSink next) ...{ m_next = next; } IMessageSink 實現#region IMessageSink 實現 public IMessageSink NextSink ...{ get ...{ return m_next; } } //同步處理消息 public IMessage SyncProcessMessage(IMessage msg) ...{ Preprocess(msg); IMessage returnMethod = m_next.SyncProcessMessage(msg); return returnMethod; } //異步處理消息(不實現) public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) ...{ throw new InvalidOperationException(); } #endregion 自定義的 AOP 方法#region 自定義的 AOP 方法 private void Preprocess(IMessage msg) ...{ //只處理方法調用 if (!(msg is IMethodMessage)) return; //獲取方法中定義的 Task 屬性,交給權限檢查類去檢查 IMethodMessage call = msg as IMethodMessage; MethodBase mb = call.MethodBase; object[] attrObj = mb.GetCustomAttributes(typeof(Task), false); if (attrObj != null) ...{ Task attr = (Task)attrObj[0]; if(!string.IsNullOrEmpty(attr.Name)) AzHelper.PermissionCheck(attr.Name); } // Type type = Type.GetType(call.TypeName); } #endregion } public class PermissionCheckProperty : IContextProperty, IContributeObjectSink ...{ IContributeObjectSink 實現,將 AOP 類加入消息處理鏈#region IContributeObjectSink 實現,將 AOP 類加入消息處理鏈 public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next) ...{ return new SecurityAspect(next); } #endregion IContextProperty 實現#region IContextProperty 實現 public string Name ...{ get ...{ return "PermissionCheckProperty"; } } public void Freeze(Context newContext) ...{ } public bool IsNewContextOK(Context newCtx) ...{ return true; } #endregion } //特性定義,用于 Consumer [AttributeUsage(AttributeTargets.Class)] public class PermissionCheckAttribute : ContextAttribute ...{ public PermissionCheckAttribute() : base("PermissionCheck") ...{ } public override void GetPropertiesForNewContext(IConstructionCallMessage ccm) ...{ ccm.ContextProperties.Add(new PermissionCheckProperty()); } } }

    ?

    3. 定義用于權限檢查的兩個類:AzMan、AzHelper

    這兩個類的功能是從 XML 配置文件中讀入 Role 和 Task 的映射關系,以確定 Role 中是否包含 Task 的引用,從而確定當前 Role 是否具有對此 Task 的權限。

    注:這里可根據項目的實際情況,如果你的 Role 和 Task 的映射關系是存放在 Windows 的授權管理器(Authorizatiom Manager)或數據庫中,你可以使用自已
    的方法來替換下列類。

    在本例中,我的 Role 和 Task 的關系是存放在 XML 文件中,XML文件的格式如下所示:

    <?xml version="1.0" encoding="utf-8"?> <ACL> <Tasks> <Task Name="AddItem" Description="增加" /> <Task Name="ModifyItem" Description="修改" /> <Task Name="RemoveItem" Description="刪除" /> <Task Name="ListItem" Description="獲取列表" /> </Tasks> <Roles> <Role Name="Manager"> <Task Name="AddItem" /> <Task Name="ModifyItem" /> <Task Name="RemoveItem" /> <Task Name="ListItem" /> </Role> </Roles> </ACL>

    AzMan.cs 完成角色/任務映射關系的檢查

    using System; using System.Collections.Generic; using System.Text; using System.Xml; namespace BusinessLogic.Security ...{ public class AzMan ...{ public static bool AccessCheck(string taskName, string[] roles, XmlDocument aclDoc) ...{ XmlNode rootNode = aclDoc.DocumentElement; XmlNodeList roleNodes,taskNodes; bool IsPermissiable = false; for (int i = 0; i < roles.Length; i++) ...{ roleNodes = rootNode.SelectNodes("Roles/Role[@Name='" + roles[i] + "']"); if (roleNodes != null) ...{ taskNodes = roleNodes.Item(0).SelectNodes("Task[@Name='" + taskName + "']"); if (taskNodes.Count != 0) ...{ IsPermissiable = true; break; } } } return IsPermissiable; } } }

    AzHelper.cs 助手類,協助其他類,更好地調用 AzMan 類的方法,以及基于性能考慮,對Role<-->Task的XML配置文件進行緩存:

    using System; using System.Collections.Generic; using System.Text; using System.Xml; using System.Web; using System.Web.Security; using System.Diagnostics; using System.Reflection; using System.Web.Caching; namespace BusinessLogic.Security ...{ public class AzHelper ...{ /**//// /// 檢查當前用戶是否具有執行當前任務的權限,如果有權限,則不做任何處理 /// 如果不具有權限,則引發異常 /// public static void PermissionCheck(string taskName) ...{ if (HttpContext.Current != null) ...{ XmlDocument aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"]; if (aclDoc == null) ...{ CacheXml(); aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"]; } string[] roles = Roles.GetRolesForUser(); if (!AzMan.AccessCheck(taskName, roles, aclDoc)) throw new UnauthorizedAccessException("訪問被拒絕,當前用戶不具有操作此功能的權限!"); } } /**//// /// 檢查當前用戶是否具有執行指定任務的權限 /// /// 任務名稱 /// True/False 是否允許執行 public static bool IsPermissible(string taskName) ...{ if (HttpContext.Current != null) ...{ XmlDocument aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"]; if (aclDoc == null) ...{ CacheXml(); aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"]; } string[] roles = Roles.GetRolesForUser(); aclDoc.Load(HttpContext.Current.Server.MapPath("~/App_Data/ACL.xml")); return AzMan.AccessCheck(taskName, roles, aclDoc); } else return true; } /**//// /// 緩存 XML 文件 /// private static void CacheXml() ...{ string fileName = HttpContext.Current.Server.MapPath("~/App_Data/ACL.xml"); XmlDocument aclDoc = new XmlDocument(); aclDoc.Load(fileName); HttpContext.Current.Cache.Insert("ACLDoc", aclDoc, new CacheDependency(fileName)); } } }


    4. 業務邏輯類的實現

    由于大多數工作都在 AOP 中實現了,所以業務邏輯類的實現較為簡單,主要分為以下幾個步驟:

    • 在類的層次定義要求 AOP 方式權限檢查的 Attribute: [PermissionCheck()]
    • 使類繼承自 ContextBoundObject 對象
    • 在方法層次上利用 Task Attribute 來定義其對應的操作(注:多個方法可以定義為同一個 Task)

    例如:ItemManager.cs

    namespace BusinessLogic ...{ [PermissionCheck()] public class ItemManager : ContextBoundObject ...{ [Task("AddItem","增加")] public void AddItem(Item item) ...{ //... } } }

    這樣就可以了,CLR 會在運行時檢查類的 PermissionCheck?Attribute,然后尋找方法上的 Task ,取出當前用戶對應的 Role ,再去進行匹配檢查,如果不能執行此操作,會拋出 UnauthorizedAccessException 的異常,在外部進行處理即可(如在 ASP.NET 中增加 ErrorPage 等)

    5. 其他相關功能的實現

    Q:如果我寫程序時,在各個業務邏輯類定義了大量的 Task ,如果統一提取出來?

    A:利用反射可取出程序集中定義的所有 Task ,代碼如下:

    List<string> dic = new List<string>(); StringBuilder sXml = new StringBuilder(""); string curDir = this.GetCurrentPath(); Assembly ass = Assembly.LoadFile(curDir + "\\AppFramework.BusinessLogic.dll"); foreach (Type t in ass.GetTypes()) ...{ MethodInfo[] mis = t.GetMethods(); foreach (MethodInfo mi in mis) ...{ object[] attrs = mi.GetCustomAttributes(false); if (attrs.Length > 0) ...{ foreach (object attr in attrs) ...{ if (attr.GetType().ToString().IndexOf("Task") >= 0) ...{ Task ta = (Task)attr; //檢查重復的 Task if (dic.IndexOf(ta.Name) < 0) ...{ dic.Add(ta.Name); sXml.Append(string.Format("\r\n ", ta.Name, ta.Description)); } } } } } //這就是所有的 Task 定義 sXml.Append("\r\n"); }

    此段代碼是將 Task 定義保存到 XML 文件中,如果你想保存到 SQL Server/Authorzatiom Manager 中,對代碼稍加修改即可。

    Q:程序中的 Role 如何實現?

    A:如果是 ASP.NET 應用程序,可以直接利用其中的 MemberShip Role 機制,還是比較簡單的

    Q:如果我想在界面上預先實現一些控制,如某用戶不能進行某項操作,則直接將其對應的 Button 禁止或隱藏(Disable/Invisible)掉,如何做?

    A:這可以利用 ASP.NET 2.0 中的表達式功能,直接檢查當前用戶的角色是否可以執行 Task ,如果不行,則利用返回的 Bool 值直接設置 Button 等控件的屬性,做法如下:

    1)在 App_Code 下定義表達式類 PermissionCheckExpressionBuilder.cs

    [ExpressionEditor(typeof(PermissionCheckExpressionBuilderEditor))] [ExpressionPrefix("PermissionCheck")] public class PermissionCheckExpressionBuilder : ExpressionBuilder ...{ public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context) ...{ string taskName = entry.Expression; return new CodePrimitiveExpression(AzHelper.IsPermissible(taskName)); } } public class PermissionCheckExpressionBuilderEditor : System.Web.UI.Design.ExpressionEditor ...{ public override object EvaluateExpression(string expression, object parseTimeData, Type propertyType, IServiceProvider serviceProvider) ...{ //return expression + ":" + parseTimeData + ":" + propertyType + ":" + serviceProvider; string taskName = expression; return AzHelper.IsPermissible(taskName); } }


    2)在 Web.Config 中加入上述表達式定義,以便可以直接在頁面上引用

    <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <expressionBuilders> <add expressionPrefix="PermissionCheck" type="PermissionCheckExpressionBuilder"/> expressionBuilders> configuration>

    3)直接在頁面控件的相應屬性上綁定表達式,如:

    • 如果能執行此操作則顯示,否則則隱藏
      <asp:Button ID="Button1" runat="server" Text="AddItem" Visible="" />
    • 如果能執行此操作則啟用,否則則禁止
      <asp:Button ID="Button2" runat="server" Text="AddItem" Enabled="" />

    4)如果想在代碼中自行檢查權限,可以直接調用相應方法,如:

    protected void Button1_Click(object sender, EventArgs e) ...{ AzHelper.PermissionCheck("AddItem"); //..其他操作 }

    5)如何建立 User<-->Role 的映射,Role<-->Task的映射

    前者較為簡單,ASP.NET 2.0 中就已經具有此功能,當然你也可以利用其 API 來實現自己的定義界面。

    對于 Role-Task 的映射來說,首先利用上面的代碼從程序集中取出所有 Task ,保存在 XML 文件中,然后在進行配置時,可以顯示 Role 和 Task ,來進行映射。

    如下圖所示:

    角色與任務的映射


    用戶與角色的映射

    http://www.850816.com/trackback.asp?tbID=44

    總結

    以上是生活随笔為你收集整理的RBAC的资料的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。