CAS 代码访问安全性 (翻译)
2009-05-12 22:57
316 查看
前言:用vs2005+vsto开发一个outlook的addin的时候,碰到了一个问题,在我机器上运行的好好的程序,用vs自己的打包安装程序安装到别的机器的时候总是显示notload,加载程序的时候出错。google了一下,遇到了一个新名词,CAS:codeaccesssecurity.找不到相关的中文文档。在codeproject上看到了这篇文章。文章比较长,有codeproject的文风,讲解的非常详细,就是一点基础都没有的人都知道他说什么,但是要耐心看。^_^RoleBasedSecurity(notbeingdiscussedinthisarticle)基于角色的安全验证
CodeAccessSecurity代码访问安全性
CLR允许代码做那些只被授权的行为,所以,CAS是一种通过阻止未授权的访问来保护资源和操作的一种安全系统。运用CAS,你可以做到:
指定你的代码能够做的
指定那些代码可以代用你的代码
唯一标识你的代码
我们将在这篇文章讨论这些问题,你应该熟悉一些术语。术语CAS包含一下这些元素:permissions许可permissionsets许可集codegroups代码组evidence物证policy策略
http://www.somewebsite.com/的代码可以属于一个代码组,包含一个特定的强类型名字的代码属于另一组,特定装配的代码又属于一个组。内置的代码组像
写下如下代码:
1privatevoidbtnWrite_click(objectsender,System.EventArgse)
{StreamWritermyFile=newStreamWriter("c://Security.txt");
myFile.WriteLine("TrustNoOne");
myFile.Close();}privatevoidbtnRead_click(objectsender,System.EventArgse)
{StreamReadermyFile=newStreamReader("c://Security.txt");
MessageBox.Show(myFile.ReadLine());
myFile.Close()}完整的版本号我们的例子才能够工作。确定你设置了你的版本号为一个固定的值,否则它会随着你的编译次数自动增加。我们标记这个装配用一个强名字,这将被用做evidence时标识代码用。这就是为什么你需要设置你的版本号为一个固定的值。
[assembly:AssemblyVersion("1.0.0.0")]就这样。。。没有什么异常。它将会写一个名字为security.txt的文件到c:.现在跑起来你的代码,它将会创建一个文件并写下一行,每件事看起来都ok。。。除非你没有c盘。现在我们要做的事把我们的装备到一个codegroup,并且设置一些permissions。还不要删除security.txt文件,我们晚点会需要它。
【图三】
【图四】
我将在下一个屏幕添加permissions到permissionset。在左边的panel,我们可以看到.NETFramework支持的所有的permissions。现在我们得到FileIOpermission属性。设置Filepath到c:/然后只选上read。所以我们没有赋予写的权限。请注意那里还有另一个选项说“准许装备自由的访问文件系统”如果这个被选上,任何事情都可以做,没有任何限制。【图五】
现在我们多添加2个p’ermissionsSecurity和UserInterface。只需要添加记住添加“准许装备自由的访问文件系统”。我很快将会解释这些属性。没有Securitypermission。我们没有权限去执行我们的代码,没有UserInterfacep’ermission,我们将不会看到UI。如果你添加了这3个permissions,你会看到有一个新的permissionset被创建,命名为
【图六】
下一个屏幕,你需要提供一个condition类型给codegroup。这些就是之前提到过的evidence。在这个例子中,我们用strongname类型。首先标识你的装配用一个strongname然后编译它。现在我们按import(导入)按钮选择你的装配。Publickey,名字和版本将从装配中萃取出来,我们不需要考虑它。现在我们到下一个页面。我们必须为我们的codegroup指定一个permissionset。因为我们已经创建了一个【图七】
【图八】
我们已经设置了许多属性,但是它将在最后讲得通。:-<好了,现在我们来跑我们得代码。我们现在做得就是把我们得代码放到一个codegroup中,并且给她对c盘得只读得权限,跑它并按那两个按钮,read工作得很好,但是当你按write得时候,一个exception抛出了,因为我们没有对c盘写得权限。下面时出错得信息。【图九】
所以多谢codeaccesssecurity,这种对资源得限制是可行的。通过CAS你可以做很多事情,我们讲在余下得文章中讨论。
System.Security.Permissions命名空间下的主要的类有:
你能找到更多的permission类在其他的命名空间,例如,
下一步,我们将看到怎么使用这些类。
2
3publiccalssMyClass
5{
7publicMyClass(){
}//allthesemethods
9publicvoidMyMethod_A(){
}//demandsunrestrictedaccessto
11publicvoidMyMethod_B(){
}//thefilesystem
13}
命令语法
命令语法用运行时方法调用创建一个新的实例。publiccalssMyClass{
publicMyClass(){}publicvoidMethod_A()
{//DoSomethingFileIOPermissionmyPerm=
newFileIOPermission(PermissionState.Unrestricted);
myPerm.Demand();
//restofthecodewon'tgetexecutedifthisfailed//DoSomething
}//Nodemands
publicvoidMethod_B()
{
//DoSomething
}
}
他们2个的主要的不同是,声明调用是在编译的时候调用而命令调用是在运行时的时候。请注意编译的时候指的是在jit编译的时候。
这里有一些行为可能与permissions冲突。首先,我们看一下声明的语法。用
Clipboard=UIPermissionClipboard.AllClipboard)]
或者添加
Clipboard=UIPermissionClipboard.AllClipboard,
Window=UIPermissionWindow.AllWindows)]
如果你想要声明一个permission用自由访问,你可以这样做:
[UIPermission(SecurityAction.Demand,Unrestricted=true)]
当你使用命令语法,你可以使用构造函数来传递这些值,然后在属性中调用它的action。我们用
newRegistryPermission(RegistryPermissionAccess.AllAccess,
"HKEY_LOCAL_MACHINE//Software");
myRegPerm.Demand();
如果你想自由访问这些资源,你可是使用
RegistryPermission(PermissionState.Unrestricted);
myRegPerm.Demand();
这是你调用任何permissions类所需要知道的在.NETFramework.。现在,我们将详细讨论actions
图十】
不同的装配和不同的方法在相同的装配通过栈道来检查。
现在回到需求。这里有3种类型的需求。DemandLinkDemandInheritanceDemand
CodeAccessSecurity代码访问安全性
CLR允许代码做那些只被授权的行为,所以,CAS是一种通过阻止未授权的访问来保护资源和操作的一种安全系统。运用CAS,你可以做到:
指定你的代码能够做的
指定那些代码可以代用你的代码
唯一标识你的代码
我们将在这篇文章讨论这些问题,你应该熟悉一些术语。术语CAS包含一下这些元素:permissions许可permissionsets许可集codegroups代码组evidence物证policy策略
Permissions
Permissions声明对受保护的资源的访问或者是执行受保护的操作的能力。.NetFrameword提供了一些Permission的类,像FileIOPermission(对文件起作用),UIPermission(允许使用一些用户接口),SecurityPermission(对于执行代码甚至是绕过安全机制这是必须的)。我将不会列举所有的Permission类在这里,他们列举在下面。Permissionsets
一个PermissionSet是一个permission的容器。你可以把FileIOPermission和UIPermission放到你的Permissionset中,然后叫他“My_PermissionSet”。一个Permissionset可以包含许多permissions。FullTrust,
LocalIntranet,
Internet,
Execution和
Nothing
是.netframework内置的一些permissionsets。FullTrust包含所有的permissions,而Nothing则表示什么都不包括,甚至连执行的权利都没有。
Codegroups
Codegroup是一个特定条件下的代码逻辑组。My_Computer_Zone,
LocalIntranet_Zone,
Internet_Zone
等等。像permissionsets,我们可以创建代码组来满足我们基于evidence的需求。Site,
StrongName,
Zone,
URL
是一些evidence的类型。
Policy
Securitypolicy是可配置的规则的集合,当我们决定赋予代码一定的许可。有4个机制的等级Enterprise,
Machine,
User和
ApplicationDomain
,每种操作不互相依赖。每个等级有它自己的codegroups和permissionsets。他们的层次如下:
【图一】
Ok
,理论说完了,让我们把理论付诸实践。
小例子
让我们创建一个新的windows应用程序。添加2个button到存在的form上。我们将用到文件系统,所以添加System.IO命名空间。
usingSystem.IO;
【图二】
写下如下代码:
1privatevoidbtnWrite_click(objectsender,System.EventArgse)
{StreamWritermyFile=newStreamWriter("c://Security.txt");
myFile.WriteLine("TrustNoOne");
myFile.Close();}privatevoidbtnRead_click(objectsender,System.EventArgse)
{StreamReadermyFile=newStreamReader("c://Security.txt");
MessageBox.Show(myFile.ReadLine());
myFile.Close()}完整的版本号我们的例子才能够工作。确定你设置了你的版本号为一个固定的值,否则它会随着你的编译次数自动增加。我们标记这个装配用一个强名字,这将被用做evidence时标识代码用。这就是为什么你需要设置你的版本号为一个固定的值。
[assembly:AssemblyVersion("1.0.0.0")]就这样。。。没有什么异常。它将会写一个名字为security.txt的文件到c:.现在跑起来你的代码,它将会创建一个文件并写下一行,每件事看起来都ok。。。除非你没有c盘。现在我们要做的事把我们的装备到一个codegroup,并且设置一些permissions。还不要删除security.txt文件,我们晚点会需要它。
NETConfigurationTool
我们可以用两种方式来做这个工作,从.NETConfigurationTool或者是用命令行调用caspol.exe。首先我们用.NETConfigurationTool。从控制面板——》管理工具-》Microsoft.NETFrameworkConfiguration。你也可以用“mscorcfg.msc”在.net命令行。你可以做很cool的事情通过这个工具。。但是目前我们只是对设置代码访问权限感兴趣。Creatinganewpermissionset创建一个新的permissionset
展开runtimesecuritypolicy节点。你可以看到安全机制级别Enterprise,
Machine和
User
。我们将改变Machine机制的安全集合。首先我们创建我们自定义的permissionset。右击permissionsets节点选择new。因为我到别的易记住的名字,我命名它为MyPermissionSet.
我将在下一个屏幕添加permissions到permissionset。在左边的panel,我们可以看到.NETFramework支持的所有的permissions。现在我们得到FileIOpermission属性。设置Filepath到c:/然后只选上read。所以我们没有赋予写的权限。请注意那里还有另一个选项说“准许装备自由的访问文件系统”如果这个被选上,任何事情都可以做,没有任何限制。
现在我们多添加2个p’ermissionsSecurity和UserInterface。只需要添加记住添加“准许装备自由的访问文件系统”。我很快将会解释这些属性。没有Securitypermission。我们没有权限去执行我们的代码,没有UserInterfacep’ermission,我们将不会看到UI。如果你添加了这3个permissions,你会看到有一个新的permissionset被创建,命名为
MyPermissionSet.
Creatinganewcodegroup创建一个新的代码组
现在我们创建一个codegroup然后设置一些条件,所以我们的装配将会是这个codegroup的一员。注意在codegroup机电,All_Code是父节点。右击All_Code节点选择new。创建codegroup向导将呈现在你面前。我将命名它为MyCodeGroup.
【图六】
下一个屏幕,你需要提供一个condition类型给codegroup。这些就是之前提到过的evidence。在这个例子中,我们用strongname类型。首先标识你的装配用一个strongname然后编译它。现在我们按import(导入)按钮选择你的装配。Publickey,名字和版本将从装配中萃取出来,我们不需要考虑它。现在我们到下一个页面。我们必须为我们的codegroup指定一个permissionset。因为我们已经创建了一个
MyPermissionSet,,我们从listbox中选他。
ExclusiveandLevelFinal
如果你还没有被。NETconfiguration默认的安全设置搞混淆,你的装配已经属于另一个内置的codegroupMy_Computer_Zone
。当permission被计算,如果一个特别的装配属于多个codegroup在相同的机制级别,最后的permissions将是所有的codegroup的permissions的集合。我将晚点解释怎么计算permissions,现在我们只需要跑我们的装配用我们的permissionset,就是用MyPermissionSet关联的MyCodeGroup.所以我们必须设置其他的属性来达到这个目的。右击新创建的MyCodeGroup节点选择属性。选择checkbox"Thispolicylevelwillonlyhavethepermissionsfromthepermissionsetassociatedwiththiscodegroup."这个机制等级的permission只包含与这个codegroup关联的permissionset。这个叫Exclusive属性。如果这个被选上了,运行时将不会允许除关联到这个codegroup的permissions。另一个选项叫做
LevelFinal.这两个属性将在计算permissions的时候起作用,我们将详细解释它在下面。
我们已经设置了许多属性,但是它将在最后讲得通。:-<好了,现在我们来跑我们得代码。我们现在做得就是把我们得代码放到一个codegroup中,并且给她对c盘得只读得权限,跑它并按那两个按钮,read工作得很好,但是当你按write得时候,一个exception抛出了,因为我们没有对c盘写得权限。下面时出错得信息。
所以多谢codeaccesssecurity,这种对资源得限制是可行的。通过CAS你可以做很多事情,我们讲在余下得文章中讨论。
FunctionsofCodeAccessSecurity
根据文档,CAS充当了一下这些功能:(直接从文档上复制过来的)Definespermissionsandpermissionsetsthatrepresenttherighttoaccessvarioussystemresources.Enablesadministratorstoconfiguresecuritypolicybyassociatingsetsofpermissionswithgroupsofcode(codegroups).Enablescodetorequestthepermissionsitrequiresinordertorun,aswellasthepermissionsthatwouldbeusefultohave,andspecifieswhichpermissionsthecodemustneverhave.Grantspermissionstoeachassemblythatisloaded,basedonthepermissionsrequestedbythecodeandontheoperationspermittedbysecuritypolicy.Enablescodetodemandthatitscallershavespecificpermissions.Enablescodetodemandthatitscallerspossessadigitalsignature,thusallowingonlycallersfromaparticularorganizationorsitetocalltheprotectedcode.Enforcesrestrictionsoncodeatruntimebycomparingthegrantedpermissionsofeverycalleronthecallstacktothepermissionsthatcallersmusthave.我们已经做了最顶上的2个,那是管理的部分。有一个独立的命名空间我们还没有看过System.Security
,这个是用来实现安全的。
SecurityNamespace
System.Security
命名空间下的主要的类有:
Classes | Description |
CodeAccessPermission | 定义下面的结构所有的代码访问权限 |
PermissionSet | 申明一个包含不同permissions的集合 |
SecurityException | 当检测到安全错误的时候抛出的异常 |
Classes | Description |
EnvironmentPermission | 控制对系统和用户环境变量的访问权限 |
FileDialogPermission | 通过文件对话框控制对文件和文件夹的访问权限 |
FileIOPermission | 控制对文件和文件夹的访问权限 |
IsolatedStorageFilePermission | 指定对私有的虚拟文件系统的使用方式. |
IsolatedStoragePermission | 指定对普通的独立存储的访问权限 |
ReflectionPermission | 控制对metadata访问通过System.ReflectionAPIs. |
RegistryPermission | 控制对注册表的访问 |
SecurityPermission | 描叙安全的permissions应用到code上 |
UIPermission | 控制UI和键盘的权限 |
SocketPermission和
WebPermission在
System.Net
。SqlClientPermission在
System.Data.SqlClient命名空间,
PerformanceCounterPermission在
System.Diagnostics命名空间等等。
下一步,我们将看到怎么使用这些类。
Declarativevs.Imperative(声明和命令)
你在写代码的时候可以用两种不同的语法,声明和命令。Declarativesyntax声明语法
生命语法用需要的安全信息属性去标识方法,类或者是装配。所以当编译的时候,他们替换相应的元数据章节。1[FileIOPermission(SecurityAction.Demand,Unrestricted=true)]2
3publiccalssMyClass
5{
7publicMyClass(){
}//allthesemethods
9publicvoidMyMethod_A(){
}//demandsunrestrictedaccessto
11publicvoidMyMethod_B(){
}//thefilesystem
13}
命令语法
命令语法用运行时方法调用创建一个新的实例。publiccalssMyClass{
publicMyClass(){}publicvoidMethod_A()
{//DoSomethingFileIOPermissionmyPerm=
newFileIOPermission(PermissionState.Unrestricted);
myPerm.Demand();
//restofthecodewon'tgetexecutedifthisfailed//DoSomething
}//Nodemands
publicvoidMethod_B()
{
//DoSomething
}
}
他们2个的主要的不同是,声明调用是在编译的时候调用而命令调用是在运行时的时候。请注意编译的时候指的是在jit编译的时候。
这里有一些行为可能与permissions冲突。
UIPermission
来说,声明语法意思使用属性,所以我们实际使用UIPermissionAttribute,当你打开msdn你会看到这些属性:Action-SecurityAction枚举的一个值Unrestricted–自由访问Clipboard–对键盘的访问权限,UIPermissionClipboard枚举的一个值(UIPermissionspecific)Window–对窗体的访问权限UIPermissionWindow的一个值。
Action和
Unrestricted
属性是通常类的permission。Clipboard和
Window
用来指明UIPermission。你必须提供action你使用其他属性的你用到的permission类。所以在这种情况下,你可以像这样写:[UIPermission(SecurityAction.Demand,
Clipboard=UIPermissionClipboard.AllClipboard)]
或者添加
Clipboard和
Window
两个属性:[UIPermission(SecurityAction.Demand,
Clipboard=UIPermissionClipboard.AllClipboard,
Window=UIPermissionWindow.AllWindows)]
如果你想要声明一个permission用自由访问,你可以这样做:
[UIPermission(SecurityAction.Demand,Unrestricted=true)]
当你使用命令语法,你可以使用构造函数来传递这些值,然后在属性中调用它的action。我们用
RegistryPermission
。RegistryPermissionmyRegPerm=
newRegistryPermission(RegistryPermissionAccess.AllAccess,
"HKEY_LOCAL_MACHINE//Software");
myRegPerm.Demand();
如果你想自由访问这些资源,你可是使用
PermissionState
枚举用如下的方法:RegistryPermissionmyRegPerm=new
RegistryPermission(PermissionState.Unrestricted);
myRegPerm.Demand();
这是你调用任何permissions类所需要知道的在.NETFramework.。现在,我们将详细讨论actions
SecurityDemands
需求用来保证每一个调用你代码的调用者(间接的或者是直接的),已经得到需要的permission。这个通过一个栈来完成。什么...一个老鼠道?不,那是你女朋友做的,我的意思是一个栈道。请求一个permission,运行时安全系统浏览栈,比较每个调用者准许的permissions和被请求的permission。如果任何一个调用栈不能找到请求的permission,然后SecurityException
抛出。请看如下的图:
不同的装配和不同的方法在相同的装配通过栈道来检查。
现在回到需求。这里有3种类型的需求。DemandLinkDemandInheritanceDemand
相关文章推荐
- 代码访问安全性(CAS)了解
- 了解 .NET Framework 2.0 中“代码访问安全性”(CAS) 的新特点
- 了解 .NET Framework 2.0 中“代码访问安全性”(CAS) 的新特点
- C#强化系列文章九:代码访问安全性使用
- OpenCV:Mat元素访问方法、性能、代码复杂度以及安全性分析
- C#强化系列文章九:代码访问安全性使用
- C#安全性之代码访问安全和角色安全小记
- OpenCV:Mat元素访问方法、性能、代码复杂度以及安全性分析
- C#安全性之代码访问安全和角色安全小记
- ASP.NET 代码访问安全性
- 代码访问安全性
- C#笔记32:FRAMEWORK安全性之代码访问安全和角色安全
- CAS代码访问安全问题(1)
- .NET中唯一一个非CAS代码访问权限类:PrincipalPermission
- FRAMEWORK安全性之代码访问安全和角色安全
- OpenCV:Mat元素访问方法、演出、代码的复杂性和安全性分析
- C#强化系列文章九:代码访问安全性使用
- .NET的代码访问安全(CAS)机制
- JavaScript(XMLHttpRequest)跨域访问解决办法及安全性问题(附java写的proxy代码)
- 代码访问安全性使用