天天看點

C#中二進制運算在權限驗證的應用

如何記錄一個權限呢,比如一個使用者,他有一個權限值,最大可表示為2的64次方減1,是以,這個值有64個二進制位,那麼,每一位要麼是0,要麼是1,是以,如果每一位表示一種權限的話,就可以表示64種權限了,是以,隻要對指定的一位進行判斷是0還是1,就可以驗證使用者的權限了。對于每一個操作的權限值,可以用一個二進制數來表示,每個權限值,隻能是(0),(10),(100),(1000),也就是說,是2的N次方,在MSSQL2000中,最大的整數是bigint類型的,最大可以表示64種操作。當然,這個是遠遠不夠的。是以可以給權限分組。比如,可分為文員,主管,經理,那麼,我們最多可以分64個組,N0到N64組,第N個組的權限值(rolevalue)就可以用2的N-1次方來表示,是以,可以表示64個權限組了。這樣,不同的使用者,可以屬于1個或是多個權限組,一個權限組,可能包括多個使用者,同理,對于一個操作,可能會屬于多個權限組,一個權限組,肯定要包括多個操作。是以,使用者與操作是通過權限組聯系以一起的。權限組與使用者,與操作之間的對應關系,都是一對多的關系。

現在說說用C#來實作,不是在SQL中實作。

在資料庫中的表:

操作組:

opname     oprolevalue

填寫             3             

修改             3

删除           11

送出             6

稽核           12

權限組:

rolename  rolevalue

文員           1

主管           2

經理           4

總監           8

使用者資訊:

username userrolevalue

u1                5

在C#中:

Long userrolevalue ;//使用者的權限值,根據他屬于的權限組,這個值會不同

Long oprolevalue   ;//一個操作的權限值,根據他屬于的權限組,這個值會不同

1、權限的賦予(或運算)

userrolevalue = userrolevalue | oprolevalue

假設一個使用者u1,他的初始權限值為0(00000000)。如果要指定他有經理的權限,經理的權限值為4(00000100),在第三個二進制位為1。

很顯然,userrolevalue =  0 | 4 ,值為4,如果u1要同時具有文員、主管、經理的權限呢,

userrolevalue = 0 | 1   00000000 | 00000001  = 00000001

userrolevalue = 1 | 2   00000001 | 00000010  = 00000011

userrolevalue = 3 | 4   00000011 | 00000100  = 00000111

這樣,第1、2、3位都是1了,用 “或”的好處就是隻改變指定位的值,如果使用者已經有了該權限,再賦予一次,也不會出錯,但是直接簡單的用加法來做,這會出錯了,如下:

userrolevalue = 7 | 4   00000111 | 00000100  = 00000111

2、權限的除去(求補、與運算)

userrolevalue = userrolevalue & (~oprolevalue)

假設一個使用者u1,他的初始權限值為7(00000111),說明他能做文員、主管、經理權限組所能作的所有操作。如果不想讓他有主管權限組能作的操作呢,那麼,就要把他的權限值變為00000101,而主管權限組的權限值是00000010,顯然簡單的用減法,肯定也是不行的,但是先對00000010作補運算,可以得到11111101,再同00000111作與運算,就得到了00000101,這樣就隻對第二位作了改變,不會影響到其它位,我們的目的也就達到了。

對于一個操作,哪些權限組能操作它,也可以用與運算來做,不讓某些權限組有些操作的權限,也可以先求補,再作與運算來解決。

3、權限的驗證(與運算)

(userrolevalue & oprolevalue) != 0

對于某使用者,有沒有某操作的權限,隻要判斷它們兩個是不是屬于同一個,或多個權限組就可以了,是以用與運算就最合适不過了。

比如u1使用者,他的權限值是5(文員組、經理組00000101),對于填寫操作的權限值是00000011,說明對于文員組與主管組有填寫的權限。

因為 00000101 & 00000011 == 1。對于一個文員,他隻屬于文員組,他的權限值肯定是00000001了,對于送出操作00000110,因為00000101 &00000001 == 0,是以,他也就沒有送出操作的權限了。

此的驗證方法,還可以用在菜單權限的驗證上來。權限值還可以是Binary資料類型的,此類型的位數可以很大,是以可以用作不分權限組的情況。