Posted on 2008-12-09 21:35
玄铁剑 阅读(359)
评论(0) 编辑 收藏 引用 所属分类:
ASP.NET相关
Microsoft Corporation
目标
使用本单元以:
适用于
本单元适用于下列产品和技术:
-
Microsoft® Windows® 2000 Server 和 Windows 2000 Professional、Windows Server™ 2003、Windows XP Professional 操作系统
-
Internet Information Server (IIS)
-
Microsoft .NET Framework 1.1
如何使用本单元
要从本单元受益最多:
本页内容
摘要
须知
创建 EncryptionPermission 类
创建 EncryptionPermissionAttribute 类
在 GAC 中安装权限程序集
更新 DPAPI 托管包装代码
从中等信任的 Web 应用程序调用 DPAPI
摘要
.NET Framework 的代码访问安全性 (CAS) 功能可扩展。这使您能够实现自己的权限以控制到重要自定义功能的访问。
本单元主要说明如何创建自定义 CAS 权限以控制到托管数据保护 API (DPAPI) 包装代码的编程访问。该代码在以下站点的 MSDN 库文章“如何:创建 DPAPI 库”中进行阐述:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT07.asp。
须知
代码访问安全性权限必须源自 System.Security.CodeAccessPermission,它可实现由 IPermission 接口定义的 Demand 方法,同时还可实现其他方法,如 IStackWalk 接口定义的 Assert、Deny 以及 PermitOnly 。
代码访问权限(不是身份权限)还可实现 IUnrestrictedPermission 接口,以指示该权限是不受限制的权限集的一部分。这意味着该权限会被自动授予任何具有完全信任的代码。本单元中使用的自定义 EncryptionPermission 的继承层次结构如图 1 所示。
图 1. 自定义 EncryptionPermission 继承层次结构
自定义 EncryptionPermission 类维护以下状态:
创建 EncryptionPermission 类
EncryptionPermission 类是自定义权限实现,用于授权到非托管 DPAPI 功能的访问。
创建 CustomPermission 类
-
创建新的 Visual C#TM 开发工具“类库”项目 CustomPermission,并将 class1.cs 重命名为 EncryptionPermission.cs。
-
向该程序集添加强名称,以便可将其安装在 GAC 中。使用 assemblyinfo.cs 中的以下属性:
[assembly: AssemblyKeyFile(@"..\..\CustomPermissions.snk")]
-
使用固定的程序集版本。
[assembly: AssemblyVersion("1.0.0.1")]
-
将以下 using 语句添加到 EncryptionPermission.cs 顶端。
using System.Security;
using System.Security.Permissions;
-
将以下枚举类型添加到 CustomPermissions 命名空间。
[Flags, Serializable]
public enum EncryptionPermissionFlag
{Encrypt = 0x01, Decrypt = 0x02}
[Flags, Serializable]
public enum StorePermissionFlag
{User = 0x01, Machine = 0x02}
-
利用 [Serializable] 属性向 EncryptionPermission 类添加序列化支持,然后将其从 CodeAccessSecurity 和 IUnrestrictedPermission 导出。.并且,密封该类,如下所示。
[Serializable]
public sealed class EncryptionPermission : CodeAccessPermission,
IUnrestrictedPermission
-
添加两个私有成员变量以维持权限状态。
private EncryptionPermissionFlag _permFlag;
private StorePermissionFlag _storePermFlag;
-
用以下构造函数替换默认的构造函数。
// It is convention for permission types to provide a constructor
// that accepts the PermissionState enumeration.
public EncryptionPermission(PermissionState state)
{
if (state.Equals(PermissionState.Unrestricted))
{
_permFlag = EncryptionPermissionFlag.Encrypt |
EncryptionPermissionFlag.Decrypt;
_storePermFlag = StorePermissionFlag.User | StorePermissionFlag.Machine;
}
else
{
_permFlag &= ~(EncryptionPermissionFlag.Encrypt |
EncryptionPermissionFlag.Decrypt);
_storePermFlag &= ~(StorePermissionFlag.User |
StorePermissionFlag.Machine);
}
}
// This constructor allows you to specify the encryption type (encrypt
// or decrypt) by using the EncryptionPermissionFlag enumeration and the DPAPI
// key store to use (user or machine) as defined by the StorePermissionFlag
// enumeration.
public EncryptionPermission(EncryptionPermissionFlag cipher,
StorePermissionFlag store)
{
_permFlag = cipher;
_storePermFlag = store;
}
public EncryptionPermission()
{
_permFlag &= ~EncryptionPermissionFlag.Encrypt |
EncryptionPermissionFlag.Decrypt;
_storePermFlag &= ~(StorePermissionFlag.User | StorePermissionFlag.Machine);
}
-
添加以下公共属性以允许使用者应用程序设置权限类状态。
// Set this property to true to allow encryption.
public bool Encrypt
{
set {
if(true == value)
{
_permFlag |= EncryptionPermissionFlag.Encrypt;
}
else
{
_permFlag &= ~EncryptionPermissionFlag.Encrypt;
}
}
get {
return (_permFlag & EncryptionPermissionFlag.Encrypt).Equals(
EncryptionPermissionFlag.Encrypt);
}
}
// Set this property to true to allow decryption.
public bool Decrypt
{
set {
if(true == value)
{
_permFlag |= EncryptionPermissionFlag.Decrypt;
}
else
{
_permFlag &= ~EncryptionPermissionFlag.Decrypt;
}
}
get {
return (_permFlag & EncryptionPermissionFlag.Decrypt).Equals(
EncryptionPermissionFlag.Decrypt);
}
}
// Set this property to true to use the DPAPI machine key.
public bool MachineStore
{
set {
if(true == value)
{
_storePermFlag |= StorePermissionFlag.Machine;
}
else
{
_storePermFlag &= ~StorePermissionFlag.Machine;
}
}
get {
return (_storePermFlag & StorePermissionFlag.Machine).Equals(
StorePermissionFlag.Machine);
}
}
// Set this property to true to use the DPAPI user key.
public bool UserStore
{
set {
if(true == value)
{
_storePermFlag |= StorePermissionFlag.User;
}
else
{
_storePermFlag &= ~StorePermissionFlag.User;
}
}
get {
return (_storePermFlag & StorePermissionFlag.User).Equals(
StorePermissionFlag.User);
}
}
-
实现 IPermission.Copy。这会创建与当前权限实例完全相同的副本,并将其返回到调用方。
public override IPermission Copy()
{
return new EncryptionPermission(_permFlag, _storePermFlag);
}
-
实现 IPermission.Intersect。这会返回一个权限对象,该对象即当前权限和提供权限之间的交集。
public override IPermission Intersect(IPermission target)
{
// An input of null indicates a permission with no state.
// There can be no common state, so the method returns null.
if (target == null)
return null;
if (!(target.GetType().Equals(this.GetType())))
throw new ArgumentException(
"Argument must be of type EncryptionPermission.");
// Cast target to an EncryptionPermission.
EncryptionPermission targetPerm = (EncryptionPermission)target;
EncryptionPermissionFlag intersectEncryption = this._permFlag &
targetPerm._permFlag;
StorePermissionFlag intersectStore = this._storePermFlag &
targetPerm._storePermFlag;
return new EncryptionPermission(intersectEncryption, intersectStore);
}
-
实现 IPermission.Union。这会返回一个权限对象,该对象即当前权限和提供权限的并集。
public override IPermission Union(IPermission target)
{
if (target == null)
return Copy();
if (!(target.GetType().Equals(this.GetType())))
throw new ArgumentException(
"Argument must be of type EncryptionPermission.");
// Cast the target to an EncryptionPermission.
EncryptionPermission targetPerm = (EncryptionPermission)target;
EncryptionPermissionFlag unionEncryption = this._permFlag |
targetPerm._permFlag;
StorePermissionFlag unionStore = this._storePermFlag |
targetPerm._storePermFlag;
return new EncryptionPermission(unionEncryption, unionStore);
}
-
实现 IPermission.IsSubsetOf。该方法会返回一个布尔值,以指示当前权限是否是提供权限的子集。要成为子集,则当前权限中状态的每一项也必须位于目标权限内。
public override bool IsSubsetOf(IPermission target)
{
// An input of null indicates a permission with no state.
// The permission can only be a subset if it's in a similar empty state.
bool canEncrypt, canDecrypt;
bool canUseMachineStore, canUseUserStore;
bool canTargetEncrypt, canTargetDecrypt;
bool canTargetUseMachineStore, canTargetUseUserStore;
canEncrypt = (this._permFlag &
EncryptionPermissionFlag.Encrypt).
Equals(EncryptionPermissionFlag.Encrypt);
canDecrypt = (this._permFlag &
EncryptionPermissionFlag.Decrypt).
Equals(EncryptionPermissionFlag.Decrypt);
canUseMachineStore = (this._storePermFlag &
StorePermissionFlag.Machine).
Equals(StorePermissionFlag.Machine);
canUseUserStore = (this._storePermFlag &
StorePermissionFlag.User).
Equals(StorePermissionFlag.User);
if (target == null)
{
if ((canEncrypt == false && canDecrypt == false) && (canUseMachineStore ==
false && canUseUserStore == false))
return true;
else
return false;
}
if (!(target.GetType().Equals(this.GetType())))
throw new ArgumentException(
"Argument must be of type EncryptionPermission.");
// Cast the target to an EncryptionPermission.
EncryptionPermission targetPerm = (EncryptionPermission)target;
canTargetEncrypt = (targetPerm._permFlag &
EncryptionPermissionFlag.Encrypt).
Equals(EncryptionPermissionFlag.Encrypt);
canTargetDecrypt = (targetPerm._permFlag &
EncryptionPermissionFlag.Decrypt).
Equals(EncryptionPermissionFlag.Decrypt);
canTargetUseMachineStore = (targetPerm._storePermFlag &
StorePermissionFlag.Machine).
Equals(StorePermissionFlag.Machine);
canTargetUseUserStore = (targetPerm._storePermFlag &
StorePermissionFlag.User).
Equals(StorePermissionFlag.User);
// Every value set (true) in this permission must be in the target.
// The following code checks to see if the current permission is a subset
// of the target. If the current permission has something that the target
// does not have, it cannot be a subset.
if(canEncrypt == true && canTargetEncrypt == false)
return false;
if(canDecrypt == true && canTargetDecrypt == false)
return false;
if(canUseMachineStore == true && canTargetUseMachineStore == false)
return false;
if(canUseUserStore == true && canTargetUseUserStore == false)
return false;
return true;
}
-
实现 ISecurityEncodable.ToXml 和 FromXml。这些方法将权限对象的实例转换为 XML 格式,反之亦然。这些方法用于支持序列化。例如,在将安全属性存储在程序集元数据中时使用这些方法。
public override SecurityElement ToXml()
{
// Create a new element. The tag name must always be IPermission.
SecurityElement elem = new SecurityElement("IPermission");
// Determine the fully qualified type name (including the assembly name) of
// the EncryptionPermission class. (The security system uses this name to
// locate and load the class.)
string name = typeof(EncryptionPermission).AssemblyQualifiedName;
// Add attributes for the class name and protocol version.
// The version must currently be 1.
elem.AddAttribute("class", name);
elem.AddAttribute("version", "1" );
if (IsUnrestricted())
{
// Using the Unrestricted attribute is consistent with the
// built-in .NET Framework permission types and helps keep
// the encoding compact.
elem.AddAttribute("Unrestricted", Boolean.TrueString);
}
else
{
// Encode each state field as an attribute of the Permission element.
// To compact, encode only nondefault state parameters.
elem.AddAttribute("Flags", this._permFlag.ToString());
elem.AddAttribute("Stores", this._storePermFlag.ToString());
}
// Return the completed element.
return elem;
}
// Converts a SecurityElement (or tree of elements) to a permission
// instance.
public override void FromXml(SecurityElement elem)
{
string attrVal = "";
// Check for an unrestricted instance.
attrVal = elem.Attribute("Unrestricted");
if (attrVal != null)
{
if(attrVal.ToLower().Equals("true"))
{
this._permFlag = EncryptionPermissionFlag.Encrypt |
EncryptionPermissionFlag.Decrypt;
this._storePermFlag = StorePermissionFlag.Machine |
StorePermissionFlag.User;
}
return;
}
//Turn off the permission and store flags.
this._permFlag &= ~(EncryptionPermissionFlag.Encrypt |
EncryptionPermissionFlag.Decrypt);
this._storePermFlag &= ~(StorePermissionFlag.Machine |
StorePermissionFlag.User);
attrVal = elem.Attribute("Flags");
if (attrVal != null)
{
if(!attrVal.Trim().Equals(""))
{
this._permFlag =
(EncryptionPermissionFlag)Enum.Parse(typeof(EncryptionPermissionFlag),
attrVal);
}
}
attrVal = elem.Attribute("Stores");
if (attrVal != null)
{
if(!attrVal.Trim().Equals(""))
{
this._storePermFlag =
(StorePermissionFlag)Enum.Parse(typeof(StorePermissionFlag),
attrVal);
}
}
}
-
实现 IUnrestrictedPermission.IsUnrestricted。如果权限实例处于不受限制的状态,则该方法返回 true。本例中,不受限制的 EncryptionPermission 实例允许代码使用 DPAPI 机器和用户存储来加密和解密数据。
public bool IsUnrestricted()
{
bool canEncrypt, canDecrypt, canUseUserStore, canUseMachineStore;
canEncrypt = (this._permFlag &
EncryptionPermissionFlag.Encrypt).
Equals(EncryptionPermissionFlag.Encrypt);
canDecrypt = (this._permFlag &
EncryptionPermissionFlag.Decrypt).
Equals(EncryptionPermissionFlag.Decrypt);
canUseUserStore = (this._storePermFlag &
StorePermissionFlag.User).
Equals(StorePermissionFlag.User);
canUseMachineStore = (this._storePermFlag &
StorePermissionFlag.Machine).
Equals(StorePermissionFlag.Machine);
return ((canEncrypt && canDecrypt) &&
(canUseUserStore && canUseMachineStore));
}
创建 EncryptionPermissionAttribute 类
.NET Framework 使用与其合作伙伴权限类相关联的属性类来编码权限实例。您需要权限属性来支持声明性安全语法。
创建 EncryptionPermissionAttribute 类
-
将一个新类文件添加到当前项目,EncryptionPermissionAttribute.cs。
-
将以下 using 语句添加到新文件的顶端。
using System.Security;
using System.Diagnostics;
using System.Security.Permissions;
-
从 CodeAccessSecurityAttribute 导出属性类,并将其密封。
public sealed class EncryptionPermissionAttribute :
CodeAccessSecurityAttribute
-
向该类添加序列化支持,并使用 AttributeUsage 属性来指示可以使用自定义权限属性的位置。
[Serializable,
AttributeUsage(AttributeTargets.Method | // Can use on methods
AttributeTargets.Constructor | // Can use on constructors
AttributeTargets.Class | // Can use on classes
AttributeTargets.Struct | // Can use on structures
AttributeTargets.Assembly, // Can use at the assembly level
AllowMultiple = true, // Can use multiple attribute
// instances per program element
// (class, method and so on)
Inherited = false)] // Can not be inherited
-
向该类添加私有成员变量以镜像由关联的权限类维持的状态。
// The following state fields mirror those used in the associated
// permission type.
private bool _encrypt = false;
private bool _decrypt = false;
private bool _machineStore = false;
private bool _userStore = false;
-
用以下构造函数替换默认的构造函数。
// Pass the action code back to the base class.
public EncryptionPermissionAttribute(SecurityAction action) : base(action)
{
}
-
添加以下公共属性以镜像这些由关联的权限类提供的各项。
public bool Encrypt
{
get {
return _encrypt;
}
set {
_encrypt = value;
}
}
public bool Decrypt
{
get {
return _decrypt;
}
set {
_decrypt = value;
}
}
public bool UserStore
{
get {
return _userStore;
}
set {
_userStore = value;
}
}
public bool MachineStore
{
get {
return _machineStore;
}
set {
_machineStore = value;
}
}
-
实现 SecurityPermissionAttribute.CreatePermission。该方法会创建一个权限对象,该对象随后被序列化并通过程序集的元数据中指定的 SecurityAction 枚举进行保留。
public override IPermission CreatePermission()
{
// The runtime automatically provides a property to indicate
// whether or not an unrestricted instance is required.
if((Unrestricted) || ((_encrypt && _decrypt) &&
(_userStore && _machineStore)))
{
return new EncryptionPermission(PermissionState.Unrestricted);
}
// Copy the state from the attribute to the permission object
EncryptionPermissionFlag cipher = 0x0;
StorePermissionFlag store = 0x0;
if(_encrypt)
cipher |= EncryptionPermissionFlag.Encrypt;
if(_decrypt)
cipher |= EncryptionPermissionFlag.Decrypt;
if(_userStore)
store |= StorePermissionFlag.User;
if(_machineStore)
store |= StorePermissionFlag.Machine;
// Return the final permission.
return new EncryptionPermission(cipher, store);
}
-
生成解决方案。
在 GAC 中安装权限程序集
您必须对实现自定义安全权限的所有程序集授予完全信任。实际上,这意味着您需要在使用程序集的计算机上安装该程序集,以确保默认的安全策略授予其完全信任。My_Computer_Zone 内的代码由默认的策略授予完全信任。
在 GAC 中安装程序集是确保代码访问安全策略授予其完全信任的一种方法。GAC 是适合于权限程序集的位置,原因在于该程序集由本地计算机上的代码访问安全策略使用,并且它对于本地计算机上安装的所有 .NET Framework 应用程序均可用。
要在本地计算机的 GAC 中安装自定义权限程序集,请运行以下命令。
gacutil.exe /i custompermission.dll
更新 DPAPI 托管包装代码
.NET Framework 类库目前并未公开 DPAPI 功能。要从 .NET Framework 应用程序调用 DPAPI,必须使用 P/Invoke。有关演示如何创建托管 DPAPI 包装程序集的代码的信息,请参阅“How To Create a DPAPI Library”。
不做进一步的修改,您只可从完全信任代码调用参考“如何……”方法文章中的托管 DPAPI 包装。若要能够从部分信任代码(例如,中等信任的 ASP.NET Web 应用程序)调用 DPAPI 包装,您必须将对非托管 DPAPI 函数的调用置于沙箱内方可。为此,需进行以下修改:
-
宣告 DPAPI 包装代码中的非托管代码权限。这意味着任何调用代码均不要求非托管代码权限。
-
通过要求自定义 EncryptionPermission 在包装内授权调用代码。根据 Demand/Assert 使用模式,Demand 调用在 Assert 调用前出现。有关安全使用 Assert 的详细信息,请参阅单元“Code Access Security in Practice”中的“Assert and RevertAssert”。
修改 DPAPI 托管包装
-
通过“如何创建 DPAPI 库”中的以下指令构建 DPAPI 托管包装。
-
向 CustomPermission 程序集添加引用。
-
从托管包装库中打开 dataprotection.cs,并在该文件顶端现有的 using 语句下添加以下 using 语句。
using System.Security;
using System.Security.Permissions;
using CustomPermissions;
-
在 dataprotection.cs 中找到 Encrypt 方法,并在该 Encrypt 方法中的外部 try 块顶端添加以下代码。
// Set the storeFlag depending on how the caller uses
// the managed DPAPI wrapper.
StorePermissionFlag storeFlag;
if(Store.USE_MACHINE_STORE == store)
{
storeFlag = StorePermissionFlag.Machine;
}
else
{
storeFlag = StorePermissionFlag.User;
}
// Demand custom EncryptionPermission.
(new EncryptionPermission(EncryptionPermissionFlag.Encrypt, storeFlag)).
Demand();
// Assert the unmanaged code permission.
(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
// Now use P/Invoke to call the unmanaged DPAPI functions.
-
将以下 finally 块添加到该 Encrypt 方法中的外部 try 块。
finally
{
CodeAccessPermission.RevertAssert();
}
-
找到 dataprotection.cs 中的 Decrypt 方法,并将以下代码添加到外部 try 块的顶端。
StorePermissionFlag storeFlag;
if(Store.USE_MACHINE_STORE == store)
{
storeFlag = StorePermissionFlag.Machine;
}
else
{
storeFlag = StorePermissionFlag.User;
}
// Demand custom EncryptionPermission.
(new EncryptionPermission(EncryptionPermissionFlag.Decrypt, storeFlag)).
Demand();
// Assert the unmanaged code permission.
(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
-
将以下 finally 块添加到该 Decrypt 方法中的外部 try 块。
finally
{
CodeAccessPermission.RevertAssert();
}
从中等信任的 Web 应用程序调用 DPAPI
要从中等信任的 Web 应用程序或任何部分信任的代码使用 DPAPI 托管包装,您必须配置代码访问安全策略以授予代码自定义 EncryptionPermission。
本步骤中,将创建测试 Web 应用程序,然后修改中等信任的 Web 应用程序的 ASP.NET 代码访问安全策略以授予其 EncryptionPermission。
创建测试 Web 应用程序
-
将新的 C# ASP.NET Web 应用程序项目添加当前解决方案。
-
向 Dataprotection.dll 程序集添加引用。
-
将以下字段添加到 Webform1.aspx。
-
一个用于要加密数据的输入字段。使用 ID txtDataToEncrypt。
-
一个用于已加密数据的字段。使用 ID txtEncryptedData。
-
一个用于已解密数据的字段。使用 ID txtDecryptedData。
-
一个 Encrypt 按钮。使用 ID btnEncrypt。
-
一个 Decrypt 按钮。使用 IDbtnDecrypt。
-
一个用于错误消息的标签。使用 ID lblError。
-
将以下 using 语句添加到现有 using 语句之下的 WebForm1.aspx.cs 顶端。
using DataProtection;
-
添加以下代码以用于 Encrypt 按钮单击事件处理程序。
private void btnEncrypt_Click(object sender, System.EventArgs e)
{
DataProtector dp = new DataProtector(
DataProtector.Store.USE_MACHINE_STORE );
try
{
byte[] dataToEncrypt = Encoding.ASCII.GetBytes(txtDataToEncrypt.Text);
// Not passing optional entropy in this example
// Could pass random value (stored by the application) for added security
// when using DPAPI with the machine store.
txtEncryptedData.Text =
Convert.ToBase64String(dp.Encrypt(dataToEncrypt,null));
}
catch(Exception ex)
{
lblError.ForeColor = Color.Red;
lblError.Text = "Exception.<br>" + ex.Message;
return;
}
lblError.Text = "";
}
-
添加以下代码以用于 Decrypt 按钮单击事件处理程序。
private void btnDecrypt_Click(object sender, System.EventArgs e)
{
DataProtector dp = new DataProtector(DataProtector.Store.USE_MACHINE_STORE);
try
{
byte[] dataToDecrypt = Convert.FromBase64String(txtEncryptedData.Text);
// Optional entropy parameter is null.
// If entropy was used within the Encrypt method, the same entropy
// parameter must be supplied here.
txtDecryptedData.Text =
Encoding.ASCII.GetString(dp.Decrypt(dataToDecrypt,null));
}
catch(Exception ex)
{
lblError.ForeColor = Color.Red;
lblError.Text = "Exception.<br>" + ex.Message;
return;
}
lblError.Text = "";
}
-
通过将以下元素添加到 <system.web> 部分内应用程序的 Web.config 文件来配置 Web 应用程序以用于中等信任。
<trust level="Medium" />
-
生成解决方案。
修改中等信任策略
-
使用 Visual Studio® .NET 或记事本打开中等信任策略文件。该策略文件位于以下位置。
%windir%\Microsoft.NET\Framework\{version}\CONFIG\web_mediumtrust.config
-
通过将以下 <SecurityClass> 元素添加到 <SecurityClasses> 元素来声明 EncryptionPermission。
<SecurityClass Name="EncryptionPermission"
Description="CustomPermission.EncryptionPermission,
CustomPermission, Version=1.0.0.1,
Culture=neutral,
PublicKeyToken=951cd7d57a536a94"/>
将 PublicKeyToken 属性值设为程序集指定的公钥标记。要提取自定义权限程序集的公钥标记,请使用以下命令。
sn -T custompermission.dll
注 使用大写 -T 开关项。
-
找到在中等信任策略文件中的 ASP.NET 命名权限集,并添加以下权限元素。
<IPermission class="EncryptionPermission"
version="1" Flags="Encrypt,Decrypt"
Stores="Machine,User">
</IPermission>
该权限授予中等信任的 Web 应用程序不受限制的 EncryptionPermission,原因在于它允许代码加密和解密数据,以及使用 DPAPI 机器和用户存储。以上元素演示了支持的语法。它等同于以下内容:
<IPermission class="EncryptionPermission"
version="1" Unrestricted="true" >
</IPermission>
通过仅使用相关的属性,您可以授予代码限制的权限。例如,要限制代码仅使用机器存储中的机器密钥解密数据,请使用以下元素。
<IPermission class="EncryptionPermission"
version="1" Flags="Decrypt"
Stores="Machine">
</IPermission>
-
保存策略文件。
现在您可以运行测试 Web 应用程序,并验证通过使用部分信任的 Web 应用程序的 DPAPI 可否加密和解密数据。
有关将高权限代码置于沙箱内和使用 ASP.NET 代码访问安全策略的详细信息,请参阅单元“Using Code Access Security with ASP.NET”。