转载:闲话权限设计三层境界
轉自:
http://www.cnblogs.com/tsoukw/archive/2010/09/27/1836485.html
?
喜歡金庸的武俠,對他那幾部小說也是樂此不疲
拿獨孤求敗來說,他的劍,從無名利劍,玄鐵重劍,到木劍乃至最后的無劍,不知道破世間多少玄機
軟件設計與用劍也頗有幾分相似之處
下面就拿大家耳熟能詳的權限設計為例,聊聊我對權限設計理解的三個層次吧
第一層:手中有劍,心中無劍
年少時,憑著手上的這把無名利劍,鋒芒畢露,以為只要有這件利器在手,這天下便唯我獨尊。
"XX,你那個薪資查詢系統,怎么誰都可以進去查啊?"
"啊?..."
"只有總經理和他的助理可以查!"
"哦..."
if(Session["UserID"]==null)
??????? throw new PermissionException("必須登錄");
string userID = Session["UserID"].ToString();
if(!(userID=="88.00" || userID=="888.00"))?? //總經理的用戶ID 88,總經理的助理用戶ID:888
???????? throw new PermissionException("您沒有訪問此頁的權限");
權限這玩意剛開始其實非常簡單,誰又能不會?
然后聽說大部分頁面都要管控,很快:
public class PermissionHelper
{
???? public static bool CheckPermission(string pageID);
}
用一個方法統一封裝那部分代碼。
再建一個table,記入哪些頁面可以給哪些user訪問
pageID? userID
-------?? --------
薪資查詢 88.00
薪資查詢 888.00
薪資輸入 99.00???? --人事主管
----------------------------------
這樣只要在PageLoad中CheckPermission一下就行
接著,又可以由要進行權限管控的頁面統一繼承一個類,然后只在這基類中call一次CheckPermission就行
public class PermissionPage:System.Web.UI.Page{
???? override PageLoad(){
????????? PermissionHelper.CheckPermission(pageID);
????? }
????? protected abstract string pageID{get;}
}
權限頁面繼承此類,override pageID,就能完成當前頁的權限管控
當然在asp.net中還有其它的一些方法,如利用asp.net的HttpModule,可以在訪問頁面之前就完成權限管控,這種方法耦合性更低,靈活性更高,不過可能就要多費一些功夫記錄一下Request的Url和PageID對應才可
url??? pageID
------------------
SalaryQuery.aspx?? 薪資查詢
SalaryEdit.aspx?? 薪資輸入
------------------------------------
昨夜西風凋碧樹。獨上高樓,望盡天涯路
執著,加上勤奮,終于利劍出鞘,手到擒來
當然,世間萬物,各有不同
有通過控制WebForm的各種控件的狀態(如Button的Enable,Visible)來控制權限的
也有在MVC中,通過在Controller中設定Attribute完成
還有控制菜單
控制數據庫中table的欄位以及增/刪/改/查的
可謂八仙過海,各顯神通,最終都在自己的勢力范圍下建功立業
劍,是好劍,也能殺人
不過卻不明白這把劍好在哪?
于是就今天用的還是青龍劍,明天卻又發現了偃月刀也很犀利,可能也就轉成刀客了
停留在此種境界,即是心中無劍,最終也不過是個劍客罷了
要做劍圣,還必須真正地研究各種不同的劍,領悟劍的本質,鍛造出適合自己風格的絕世好劍--玄鐵重劍
這也是第二層境界:手中有劍,心中也有劍
心中有劍后,手中的劍才能直指目標,更犀利,更直接,殺人于無形,真正雄霸天下。
要到這一層,除了要有“為伊消得人憔悴,衣帶漸寬終不悔”的勇氣和毅力,
還要悟
權限是什么
無非就是要讓沒有權限的人不能訪問沒有授權的物
那誰有權,誰沒權
這就是權限的表示問題
不管是01也好,Table記錄也罷,文件配置也行
最終都要告訴
人--物的對應,只能在有了這種對應之后,我們的權限管控才是物有所托。
當然,很多時候這兩者不是直接對應的,
為了某種原因,如更易管理,更易寫程式,更易提供界面等等,往往會設計一些中間過程
如人會加到群組里面,由群組來對應物
物也可以組成群組
但是不管中間多少層,最終還是人與物的對應。
最終要提供類似
HasPermission(UserID,ResourceID)(有無權限),
PermissionResource(UserID)(用戶權限資源),
PermissionUser(ResourceID)(擁有資源權限的用戶)等方法。
有了權限的表示,并不能阻止訪問沒有授權的資源,它只是一個死物,需要有地方去用它。
這就是權限的管控,它包括
1.選擇管控的地點,即在哪里下手,在哪里進行管控
有通過PageLoad,有通過HttpModule,還有通過AOP在方法調用前橫切管控等等
如果是資源權限,則可能在資源下拉框中按權限篩選,在提交時根據參數判斷資源權限等等。
最終只要你記得,這是管控的地點
如何在系統中更簡單,更方便地管控,取決于系統架構,其靈活性也讓管控地點的選擇是否順利與簡單
2.管控過程,分為四步
a.識別出人
cookie,Session,或者是c/s中的UserID變量,也可以是webservice的soap頭經過登錄后的用戶ID,還可以是IP或者手機號碼,最終都轉為權限表示中的UserID
b.識別出物
Url,參數中的變量都行,最終要轉成權限表示中的ObjectID
c.調用HasPermission(人,物)判斷權限
這是由權限表示決定的方法
d.實施管控策略
對于無權限者,或轉向無權登錄頁,或拋出異常,或Button.Visible = false最終實現權限管控
經過這個本質的識別,接下來就可以來鍛造真正的玄鐵重劍了
針對權限表示,設計一個比較通用的方案
也就是基本上能夠通用的最簡單抽象
---------------------------------
不吐不快,插播一下
在系統架構過程中,如何快速實現可供用戶測試和使用的系統才是最重要的,至于一些底層服務框架,如數據訪問,AOP橫切,IOC,日志等,并不是越完美越好,而是要簡單,要在自己全部理解的基礎上使用,有了這個基礎,就算碰到不能實現某些需求時,也可以很容易地通過自己修改去實現
就說日志吧,對于一些新手來說,完全沒必要去用log4net,直接幾行代碼使用txt就完成日志記錄了,要不然在程式出錯時,除了要找尋程式為啥出錯,還可能要去找為什么沒有日志出來
還有如AOP,先想想整體架構,為什么需要AOP,AOP何時使用,如果使用spring.net,caslte,就會出現只要一個輪子,結果將整個汽車倉庫都搬來了,不是不好,而是用不到,用不到再好的東西也等于零,關鍵是對于不熟悉的人,一旦出現問題,那維護起來也是相當麻煩
當然以上只是適用于不太熟悉的人,如果你對Castle或者log4net熟悉得就像老婆身上有哪幾顆痣,在什么地方都知道,則另當別論
好了,拉回來,不跑遠了
--------------------------------------
1:Object,Group的對應
2:User,Group的對應
基本上這個簡單的抽象,就可以完成絕大部分權限表示問題(如果真有幸,碰到了剩下5%不能完成的權限表示時,那就再去抽象一次,最終提供權限表示上的權限方法就是)
對于權限方法,也只需寫一遍,就可以用在任何權限類別上了
復制幾個權限配置的片段吧
Ajax的權限
--------------------------
Role,Object
--------------------------
Admin,*
?,PCIWeb.ProgramsHelper.Programs
?,ClientTool.*
?,WebFileBrowser_CIFiles.*
?,WebFileBrowser_PQM.*
?,WebFileBrowser_ISO.*
?,MRB.BookingService.RoomBooking
?,MRB.BookingService.RoomBookingAfterNow
*,MRB.BookingService.Cancel
*,MRB.BookingService.Booking
--PQM系統
PQM_Exced,PQM.ExcedService.*
--7S,Lean,Kaizen
PQM_CI,PQM.CI
這是直接訪問DB服務的權限
--------------------------
Role,Object
--------------------------
Admin,*
?,MRB/Room_Query
?,MRB/Borrow_Query2
--任何人都可以查詢每日超標回饋表
?,PQM/Exced_Query
?,PQM/Excem_Query
?,PQM/Excedd_Query
?,PQM/Excem_Query2
這是User與Role的對應
------------------------------
User,Role
------------------------------
850.00,Admin
850.00,PQM_Exced
206.00,PQM_Exced
54.00,Admin
54.00,PQM_Exced
其次,對于管控地點,不同的人的系統架構不同,可能實現也不一樣。
筆者的系統架構采用RIA架構 + SOA服務,
因此在服務層使用aop的橫切方式,就完成了服務權限的管控
而數據權限,也是抽象了幾個UI控件,通過PermissionResource方法過濾下拉列表框和彈出Grid,而在服務調用時,在具體的程式中直接調用HasPermission方法進行管控
融入劍本質的玄鐵重劍出爐,所向披靡
這把劍與當初那把無名利劍表面上似乎沒有什么不同,但他的鍛造過程更標準,劍招也需要內力的支撐。
舉個例子來說,
通過URL管控,可能只能用于Web
而通過管控Button的Visible,雖然能管控到WinForm,但是WebService的權限怎么辦
而明確了權限的本質后,針對各種不同的部分統一或單獨實現,做到有的放矢,不再盲目跟從。
特別是如果自己的系統針對某一范圍,更能夠實現一套符合自己的通用的權限架構。
有了這一層的實現后,第三層的境界其實也是水到渠成,這便是
手中無劍,心中有劍
劍終究有形,不管它多輕,又或多通用,到處帶著,始終會很累
只要心中有劍,就是手上拿著的是木劍也能殺人。
筆者所服務的部門留有很多舊系統,里面各種權限實現五花八門,加上移植兄弟公司的系統,里面也有單獨的權限實現,對這一部分,原來還想全部改寫,后來終于放下。
只要實現目的,管他什么手段
只是與剛開始的漫無目的不同,這時候已能十分清楚這些額外的權限是如何實現,有無漏洞等等
駕馭起來,也是順風順水
其實mvc的controller管控也非常不錯,沒有誰在這里做了漏網之魚
其實webform的control管控也運行穩定,至今順利在跑
存在即合理
為什么要去改變他們,為什么要花這么大心思去補救,去重構
生命中要做的事情太多太多 ,比權限管控更重要的事情也多得多,如何讓用戶查起來更順手,如何讓資料顯示得更舒服,如何讓畫面更流暢。。。
資源管控住了就行,管它用什么方法,合適的就是最好的。
如一個webservice
系統總共就這么一個webservice
只允許本機訪問(同一臺主機,不同系統的數據交換)
那就在方法中直接寫
if(HttpContext.Current.Request.UserHostAddress!="127.0.0.1")
??? throw new PermissionException("抱歉,你沒有訪問這個web服務的權限");
這其中不也包括了
權限表示:hardcode在代碼中,就是用戶為127.0.0.1才有權限
管理地點:執行方法的主體代碼前
識別人: HttpContext.Current.Request.UserHostAddress
識別物:就是當前管控的方法調用(在這里是隱式的)
調用權限表示方法驗證:HttpContext.Current.Request.UserHostAddress!="127.0.0.1"
無權時的動作:throw new PermissionException("抱歉,你沒有訪問這個web服務的權限")
同樣它就是一個標準的權限管控方案
信手拈來即是劍
按照權限思路,查看是否有漏洞,有則補之,無則放行
無劍一身輕
眾里尋她千百度,驀然回首,那人卻在燈火闌珊處
轉載于:https://www.cnblogs.com/yangfan/archive/2011/10/26/2225753.html
總結
以上是生活随笔為你收集整理的转载:闲话权限设计三层境界的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: div+css 你知道多少?值得一看
- 下一篇: SqliteHelper整理