用vs2005 + vsto 開發(fā)一個(gè)outlook的addin的時(shí)候,碰到了一個(gè)問題,在我機(jī)器上運(yùn)行的好好的程序,用vs自己的打包安裝程序安裝到別的機(jī)器的時(shí)候總是顯示 not load, 加載程序的時(shí)候出錯(cuò)。google了一下,遇到了一個(gè)新名詞, CAS: code access security. 找不到相關(guān)的中文文檔。在codeproject上看到了這篇文章。文章比較長(zhǎng),有codeproject的文風(fēng),講解的非常詳細(xì),就是一點(diǎn)基礎(chǔ)都沒有的人都知道他說什么,但是要耐心看。 ^_^
Role Based Security (not being discussed in this article) 基于角色的安全驗(yàn)證
Code Access Security 代碼訪問安全性
CLR 允許代碼做那些只被授權(quán)的行為,所以, CAS 是一種通過阻止未授權(quán)的訪問來保護(hù)資源和操作的一種安全系統(tǒng)。運(yùn)用 CAS ,你可以做到:
指定你的代碼能夠做的
指定那些代碼可以代用你的代碼
唯一標(biāo)識(shí)你的代碼
我們將在這篇文章討論這些問題,你應(yīng)該熟悉一些術(shù)語。
?
術(shù)語
?
CAS 包含一下這些元素:
-
permissions
?
許可
-
permission sets
許可集
-
code groups
代碼組
-
evidence
物證
-
policy
策略
Permissions
Permissions 聲明對(duì)受保護(hù)的資源的訪問或者是執(zhí)行受保護(hù)的操作的能力。 .Net Frameword 提供了一些 Permission 的類,像 FileIOPermission (對(duì)文件起作用), UIPermission (允許使用一些用戶接口), SecurityPermission (對(duì)于執(zhí)行代碼甚至是繞過安全機(jī)制這是必須的)。我將不會(huì)列舉所有的 Permission 類在這里,他們列舉在下面。
Permission sets
一個(gè)
Permission Set
是一個(gè)
permission
的容器。你可以把
FileIOPermission
和
UIPermission
放到你的
Permission set
中,然后叫他“
My_PermissionSet
”。一個(gè)
Permission set
可以包含許多
permissions
。
FullTrust
,
LocalIntranet
,
Internet
,
Execution
和
Nothing
是
.net framework
內(nèi)置的一些
permission sets
。
FullTrust
包含所有的
permissions
,而
Nothing
則表示什么都不包括,甚至連執(zhí)行的權(quán)利都沒有。
Code groups
Code group
是一個(gè)特定條件下的代碼邏輯組。
http://www.somewebsite.com/
的代碼可以屬于一個(gè)代碼組,包含一個(gè)特定的強(qiáng)類型名字的代碼屬于另一組,特定裝配的代碼又屬于一個(gè)組。內(nèi)置的代碼組像
My_Computer_Zone
,
LocalIntranet_Zone
,
Internet_Zone
等等。像
permission sets,
我們可以創(chuàng)建代碼組來滿足我們基于
evidence
的需求。
Site
,
Strong Name
,
Zone
,
URL
是一些
evidence
的類型。
Policy
Security policy
是可配置的規(guī)則的集合,當(dāng)我們決定賦予代碼一定的許可。有
4
個(gè)機(jī)制的等級(jí)
Enterprise
,
Machine
,
User
和
Application Domain
,每種操作不互相依賴。每個(gè)等級(jí)有它自己的
code groups
和
permission sets
。他們的層次如下:
【圖一】
Ok
,理論說完了,讓我們把理論付諸實(shí)踐。
?
小例子
?
讓我們創(chuàng)建一個(gè)新的
windows
應(yīng)用程序。添加
2
個(gè)
button
到存在的
form
上。我們將用到文件系統(tǒng),所以添加
System.IO
命名空間。
using System.IO;
【圖二】
寫下如下代碼:
{????
StreamWriter?myFile? = ? new ?StreamWriter( " c:\\Security.txt " );???}
myFile.WriteLine( " Trust?No?One " );???
myFile.Close();
private ? void ?btnRead_click( object ?sender,?System.EventArgs?e)
{????
StreamReader?myFile? = ? new ?StreamReader( " c:\\Security.txt " );???}
MessageBox.Show(myFile.ReadLine()); ?
myFile.Close()
完整的版本號(hào)我們的例子才能夠工作。確定你設(shè)置了你的版本號(hào)為一個(gè)固定的值,否則它會(huì)隨著你的編譯次數(shù)自動(dòng)增加。我們標(biāo)記這個(gè)裝配用一個(gè)強(qiáng)名字,這將被用做 evidence 時(shí)標(biāo)識(shí)代碼用。這就是為什么你需要設(shè)置你的版本號(hào)為一個(gè)固定的值。
[assembly: AssemblyVersion( "<chsdate isrocdate="False" islunardate="False" day="30" month="12" year="1899" w:st="on">1.0.0</chsdate>.0" )]
就這樣。。。沒有什么異常。它將會(huì)寫一個(gè)名字為 security.txt 的文件到 c:. 現(xiàn)在跑起來你的代碼,它將會(huì)創(chuàng)建一個(gè)文件并寫下一行,每件事看起來都 ok 。。。除非你沒有 c 盤?,F(xiàn)在我們要做的事把我們的裝備到一個(gè) code group ,并且設(shè)置一些 permissions 。還不要?jiǎng)h除 security.txt 文件,我們晚點(diǎn)會(huì)需要它。
NET Configuration Tool
我們可以用兩種方式來做這個(gè)工作,從 .NET Configuration Tool 或者是用命令行調(diào)用 caspol.exe 。 首先我們用 .NET Configuration Tool 。從控制面板——》管理工具-》 Microsoft .NET Framework Configuration 。 你也可以用“ mscorcfg.msc ”在 .net 命令行。你可以做很 cool 的事情通過這個(gè)工具。。但是目前我們只是對(duì)設(shè)置代碼訪問權(quán)限感興趣。
【圖三】
Creating a new permission set 創(chuàng)建一個(gè)新的 permission set
展開
runtime security policy
節(jié)點(diǎn)。你可以看到安全機(jī)制級(jí)別
Enterprise
,
Machine
和
User
。我們將改變
Machine
機(jī)制的安全集合。首先我們創(chuàng)建我們自定義的
permission set
。右擊
permission sets
節(jié)點(diǎn)選擇
new
。因?yàn)槲业絼e的易記住的名字,我命名它為
MyPermissionSet
.
【圖四】
我將在下一個(gè)屏幕添加 permissions 到 permission set 。在左邊的 panel ,我們可以看到 .NET Framework 支持的所有的 permissions ?,F(xiàn)在我們得到 File IOpermission 屬性。設(shè)置 File path 到 c:\ 然后只選上 read 。所以我們沒有賦予寫的權(quán)限。請(qǐng)注意那里還有另一個(gè)選項(xiàng)說“準(zhǔn)許裝備自由的訪問文件系統(tǒng)”如果這個(gè)被選上,任何事情都可以做,沒有任何限制。
【圖五】
現(xiàn)在我們多添加
2
個(gè)
p’ermissions
Security
和
User
Interface
。
只需要添加記住添加“準(zhǔn)許裝備自由的訪問文件系統(tǒng)”。我很快將會(huì)解釋這些屬性。沒有
Security
permission
。我們沒有權(quán)限去執(zhí)行我們的代碼,沒有
User Interface p’ermission
,我們將不會(huì)看到
UI
。如果你添加了這
3
個(gè)
permissions
,你會(huì)看到有一個(gè)新的
permission set
被創(chuàng)建,命名為
MyPermissionSet
.
?
Creating a new code group 創(chuàng)建一個(gè)新的代碼組
現(xiàn)在我們創(chuàng)建一個(gè)
code group
然后設(shè)置一些條件,所以我們的裝配將會(huì)是這個(gè)
code group
的一員。注意在
code group
機(jī)電,
All_Code
是父節(jié)點(diǎn)。右擊
All_Code
節(jié)點(diǎn)選擇
new
。創(chuàng)建
code group
向?qū)⒊尸F(xiàn)在你面前。我將命名它為
MyCodeGroup
.
【圖六】
下一個(gè)屏幕,你需要提供一個(gè)
condition
類型給
code group
。這些就是之前提到過的
evidence
。在這個(gè)例子中,我們用
strong name
類型。首先標(biāo)識(shí)你的裝配用一個(gè)
strong name
然后編譯它。現(xiàn)在我們按
import
(導(dǎo)入)按鈕選擇你的裝配。
Public key
,名字和版本將從裝配中萃取出來,我們不需要考慮它。現(xiàn)在我們到下一個(gè)頁面。我們必須為我們的
code group
指定一個(gè)
permission set
。因?yàn)槲覀円呀?jīng)創(chuàng)建了一個(gè)
MyPermissionSet
,
,我們從
list box
中選他。
【圖七】
Exclusive and LevelFinal
如果你還沒有被。
NET configuration
默認(rèn)的安全設(shè)置搞混淆,你的裝配已經(jīng)屬于另一個(gè)內(nèi)置的
code group
My_Computer_Zone
。當(dāng)
permission
被計(jì)算,如果一個(gè)特別的裝配屬于多個(gè)
code group
在相同的機(jī)制級(jí)別,最后的
permissions
將是所有的
code group
的
permissions
的集合。我將晚點(diǎn)解釋怎么計(jì)算
permissions
,現(xiàn)在我們只需要跑我們的裝配用我們的
permission set
,就是用
MyPermissionSet
關(guān)聯(lián)的
MyCodeGroup
.
所以我們必須設(shè)置其他的屬性來達(dá)到這個(gè)目的。右擊新創(chuàng)建的
MyCodeGroup
節(jié)點(diǎn)選擇屬性。選擇
check box "
This policy level will only have the permissions from the permission set associated with this code group.
"
這個(gè)機(jī)制等級(jí)的
permission
只包含與這個(gè)
code group
關(guān)聯(lián)的
permission set
。這個(gè)叫
Exclusive
屬性。如果這個(gè)被選上了,運(yùn)行時(shí)將不會(huì)允許除關(guān)聯(lián)到這個(gè)
code group
的
permissions
。另一個(gè)選項(xiàng)叫做
LevelFinal
.
這兩個(gè)屬性將在計(jì)算
permissions
的時(shí)候起作用,我們將詳細(xì)解釋它在下面。
【圖八】
我們已經(jīng)設(shè)置了許多屬性,但是它將在最后講得通。 :-<
?
好了,現(xiàn)在我們來跑我們得代碼。我們現(xiàn)在做得就是把我們得代碼放到一個(gè) code group 中,并且給她對(duì) c 盤得只讀得權(quán)限,跑它并按那兩個(gè)按鈕, read 工作得很好,但是當(dāng)你按 write 得時(shí)候,一個(gè) exception 拋出了,因?yàn)槲覀儧]有對(duì) c 盤寫得權(quán)限。下面時(shí)出錯(cuò)得信息。
【圖九】
所以多謝 code access security ,這種對(duì)資源得限制是可行的。通過 CAS 你可以做很多事情,我們講在余下得文章中討論。
Functions of Code Access Security
根據(jù)文檔, CAS 充當(dāng)了一下這些功能:(直接從文檔上復(fù)制過來的)
-
Defines
permissions
and
permission sets
that represent the right to access various system resources.
-
Enables administrators to configure
security policy
by associating sets of permissions with groups of code (
code groups
).
-
Enables code to
request
the
permissions it requires in order to run
, as well as the
permissions that would be useful to have
, and specifies which
permissions the code must never have
.
-
Grants permissions
to each assembly that is loaded, based on the permissions requested by the code and on the operations permitted by security policy.
-
Enables code to
demand
that its callers have specific permissions. Enables code to demand that its callers possess a digital signature, thus allowing only callers from a particular organization or site to call the protected code.
-
Enforces restrictions
on code at run time by comparing the granted permissions of every caller on the call stack to the
permissions that callers must have.
我們已經(jīng)做了最頂上的
2
個(gè),那是管理的部分。有一個(gè)獨(dú)立的命名空間我們還沒有看過
System.Security
,這個(gè)是用來實(shí)現(xiàn)安全的。
?
Security Namespace
System.Security
命名空間下的
主要的類有:
Classes
|
Description
|
CodeAccessPermission
|
定義下面的結(jié)構(gòu)所有的代碼訪問權(quán)限
|
PermissionSet
|
申明一個(gè)包含不同 permissions 的集合
|
SecurityException
|
當(dāng)檢測(cè)到安全錯(cuò)誤的時(shí)候拋出的異常
|
System.Security.Permissions 命名空間下的主要的類有 :
Classes
|
Description
|
EnvironmentPermission
|
控制對(duì)系統(tǒng)和用戶環(huán)境變量的訪問權(quán)限
|
FileDialogPermission
|
通過文件對(duì)話框控制對(duì)文件和文件夾的訪問權(quán)限
|
FileIOPermission
|
控制對(duì)文件和文件夾的訪問權(quán)限
|
IsolatedStorageFilePermission
|
指定對(duì)私有的虛擬文件系統(tǒng)的使用方式 .
|
IsolatedStoragePermission
|
指定對(duì)普通的獨(dú)立存儲(chǔ)的訪問權(quán)限
|
ReflectionPermission
|
控制對(duì)
metadata
訪問通過
|
RegistryPermission
|
控制對(duì)注冊(cè)表的訪問
|
SecurityPermission
|
描敘安全的 permissions 應(yīng)用到 code 上
|
UIPermission
|
控制 UI 和鍵盤的權(quán)限
|
你能找到更多的
permission
類 在其他的命名空間,例如,
SocketPermission
和
WebPermission
在
System.Net
。
SqlClientPermission
在
System.Data.SqlClient
命名空間
,
PerformanceCounterPermission
在
System.Diagnostics
命名空間等等。
下一步,我們將看到怎么使用這些類。
Declarative vs. Imperative (聲明和命令)
你在寫代碼的時(shí)候可以用兩種不同的語法,聲明和命令。
Declarative syntax 聲明語法
生命語法用需要的安全信息屬性去標(biāo)識(shí)方法,類或者是裝配。所以當(dāng)編譯的時(shí)候,他們替換相應(yīng)的元數(shù)據(jù)章節(jié)。
?2 ?
?3 ? public ?calss?MyClass
?5 ? {
?7 ? ???? public ?MyClass()?{

?9 ? ???? public ? void ?MyMethod_A()?{

11 ? ???? public ? void ?MyMethod_B()?{

13 ? }
命令語法
命令語法用運(yùn)行時(shí)方法調(diào)用創(chuàng)建一個(gè)新的實(shí)例。
{
???? public ?MyClass()?{?}
???? public ? void ?Method_A()?
????{
???????? // ?Do?Something
????????FileIOPermission?myPerm? = ?
?????????? new ?FileIOPermission(PermissionState.Unrestricted);
????????myPerm.Demand();?
???????? // ?rest?of?the?code?won't?get?executed?if?this?failed
?
???????? // ?Do?Something
????}
???? // ?No?demands
???? public ? void ?Method_B()
????{
???????? // ?Do?Something
????}
}
他們 2 個(gè)的主要的不同是,聲明調(diào)用是在編譯的時(shí)候調(diào)用而命令調(diào)用是在運(yùn)行時(shí)的時(shí)候。請(qǐng) 注意編譯的時(shí)候指的是在 jit 編譯的時(shí)候。
這里有一些行為可能與 permissions 沖突。
首先,我們看一下聲明的語法。用
UIPermission
來說,聲明語法意思使用屬性,所以我們實(shí)際使用
UIPermissionAttribute
,當(dāng)你打開
msdn
你會(huì)看到這些屬性:
-
Action - SecurityAction
枚舉的一個(gè)值
-
Unrestricted –
自由訪問
-
Clipboard –
對(duì)鍵盤的訪問權(quán)限,
UIPermissionClipboard
枚舉的一個(gè)值
(UIPermission specific)
-
Window –
對(duì)窗體的訪問權(quán)限
UIPermissionWindow
的一個(gè)值。
Action
和
Unrestricted
屬性是通常類的
permission
。
Clipboard
和
Window
用來指明
UIPermission
。你必須提供
action
你使用其他屬性的你用到的
permission
類。所以在這種情況下,你可以像這樣寫:
Clipboard = UIPermissionClipboard.AllClipboard)]
或者添加
Clipboard
和
Window
兩個(gè)屬性:
????Clipboard = UIPermissionClipboard.AllClipboard,?
??????Window = UIPermissionWindow.AllWindows)]
如果你想要聲明一個(gè) permission 用自由訪問,你可以這樣做:
當(dāng)你使用命令語法,你可以使用構(gòu)造函數(shù)來傳遞這些值,然后在屬性中調(diào)用它的
action
。我們用
RegistryPermission
。
??? new ?RegistryPermission(RegistryPermissionAccess.AllAccess,
??? " HKEY_LOCAL_MACHINE\\Software " );
myRegPerm.Demand();
如果你想自由訪問這些資源,你可是使用
PermissionState
枚舉用如下的方法:
RegistryPermission(PermissionState.Unrestricted);
myRegPerm.Demand();
這是你調(diào)用任何 permissions 類所需要知道的在 .NET Framework. ?,F(xiàn)在,我們將詳細(xì)討論 actions
Security Demands
需求用來保證每一個(gè)調(diào)用你代碼的調(diào)用者(間接的或者是直接的),已經(jīng)得到需要的
permission
。這個(gè)通過一個(gè)棧來完成。什么
...
一個(gè)老鼠道?不,那是你女朋友做的,我的意思是一個(gè)棧道。請(qǐng)求一個(gè)
permission
,運(yùn)行時(shí)安全系統(tǒng)瀏覽棧,比較每個(gè)調(diào)用者準(zhǔn)許的
permissions
和被請(qǐng)求的
permission
。如果任何一個(gè)調(diào)用棧不能找到請(qǐng)求的
permission
,然后
SecurityException
拋出。請(qǐng)看如下的圖:
圖十】
不同的裝配和不同的方法在相同的裝配通過棧道來檢查。
現(xiàn)在回到需求。這里有 3 種類型的需求。
-
Demand
-
Link Demand
-
Inheritance Demand
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
