.NET Framework 安全性基础知识

“代码访问安全性”是 .NET Framework 的一部分,它通过控制代码的执行情况来控制对资源的访问。这种安全性功能与操作系统提供的安全性不同,是附加的安全性。

工作机制

当用户运行应用程序时,.NET Framework 公共语言运行时会将其分配到某一区域。五个可能的区域为:

区域

说明

我的电脑

应用程序代码驻留在用户的计算机上。

本地 Intranet

从用户 Intranet 上的文件共享中运行应用程序代码。

Internet

从 Internet 上运行应用程序代码。

受信任站点

这些应用程序来自 Internet Explorer 中定义的“受信任”站点。

不可信站点

这些应用程序来自 Internet Explorer 中定义的“受限制”站点。

前三个区域,即**“我的电脑”“本地 Intranet”“Internet”**,是根据代码所在的位置进行分配的。在 Internet Explorer 中,通过将特定站点分配给“受信任站点”组或“不可信站点”组,可以重写分配内容。

系统管理员为每个区域均设置了特定的访问权限集。区域的安全级别可以设置为完全信任、中等信任、低信任或不信任。这些信任级别定义了应用程序可以访问的资源。在运行时,区域与其他安全证据(例如发行者、强名称、网站以及代码的 URL)共同确定授予代码的权限。有关安全证据的更多信息,请参见 证据。您无法控制用户计算机上的安全设置,而应用程序也必须在它运行时所遇到的安全设置中工作。这可能意味着,某些特定资源将拒绝应用程序的访问。例如,应用程序可能需要向文件写入数据,但用户系统却在运行时引发异常,拒绝该应用程序进行写访问。

您的工作就是开发应用程序,以处理这种情况。但这并不一定意味着应用程序需通过其他途径写入数据,而是需要预见可能无法写入数据的情况,并对这种可能性加以响应。可能需要使用更多异常处理,或使用 System.Security.Permissions 命名空间中的某些对象,使代码更加可靠。有关这些方法的简要说明,请参见本文稍后的一节“在部分信任的环境中进行开发”。

使用安装 .NET Framework 时安装的管理工具,可以设置区域的安全级别。若要了解有关在计算机上设置区域的安全级别的更多信息,请参见 管理工具

完全信任

开发人员通常会在完全信任的环境中进行工作。他们将源代码保存在硬盘中,并在自己的开发计算机上测试应用程序。在此完全信任的环境中,开发人员编译的任何代码均可以在本地计算机上运行。由于本地计算机在默认情况下被定义为完全信任环境,因此不会出现安全性异常。

部分信任

部分信任用于描述所有非完全信任的区域。部署应用程序时,它可能会移动到一个新区域中,而该区域可能未授予应用程序完全信任级别。在部分信任区域运行代码的两种最常见的情况为:

  • 运行从 Internet 下载的代码。

  • 运行驻留在网络共享 (Intranet) 中的代码。

在部分信任区域中,可能拒绝访问的一些资源示例包括:

  • 文件 I/O 操作,包括读取、写入、创建、删除或打印文件。

  • 系统组件,例如注册表值和环境变量。

  • 服务器组件,包括目录服务、注册表、事件日志、性能计数器和消息队列。

在部分信任区域中,哪些内容是不允许访问的?这很难判断。在 .NET Framework 中,每个类及其每种方法都有其各自的安全特性,其中定义了运行该方法所需的信任级别,也正是因为这些安全功能,在运行时可能无法访问安全特性。区域级别并不是简单地将信任级别映射到特性,而是授予特定类和方法的特定权限的集合。应用程序无法只查询信任级别即可预测哪些资源不可用。您可以确定应用程序是否运行在完全信任的环境中。在下一节“在部分信任的环境中进行开发”中,将介绍一种方法来实现此目的。

在部分信任的环境中进行开发

本节将使您大致了解安全性问题如何影响您编写的代码。在部分受信任环境中进行开发时,没有一种单一的解决方案。解决方案将依赖于所编写的应用程序。此外,在应用程序的执行过程中,由于信任级别可能发生更改,因此不能简单地测试现有的信任级别就继续下面的操作。

安全性异常代码

若要在部分信任的区域中进行开发,第一步便是编写可识别出现的安全性异常的代码。考虑下列代码:

Public Sub MakeABitmap()
    Dim b As New System.Drawing.Bitmap(100, 100)
    ' Some code here to draw a nice picture in the bitmap
    b.Save("c:\PrettyPicture.bmp")
End Sub
public void MakeABitmap()
{
    System.Drawing.Bitmap b =
        new System.Drawing.Bitmap(100, 100);
    // Some code here to draw a nice picture in the bitmap
    b.Save("c:\\PrettyPicture.bmp");
}

如果项目和项目程序集存储在计算机的硬盘上,且您是本地计算机上“管理员”组的成员,则运行此方法不会引发异常。如果将此应用程序部署到 Intranet 上,则当应用程序尝试保存位图对象时,可能会引发 SecurityException。如果此代码周围无 Try...Catch...Finally 语句 (Visual Basic)try-catch-finally (C# Reference) 块,则应用程序将因异常而终止。这样的用户体验可能不会令人满意。如果您添加了异常处理代码,应用程序就可以:

  • 警告用户应用程序无法完成它需要完成的所有任务。

  • 清理现有的所有对象,以便在 catch 块后运行的代码不会失败。

您可以修改用于保存位图的代码,如下所示。所添加的代码可警告用户,由于安全性拒绝,文件未被保存;该代码还会将安全性失败与其他文件 I/O 失败(例如文件名错误)相区别。此方法不会产生任何安全漏洞。用户可以选择修改安全性以信任应用程序,或选择不运行应用程序。

Public Sub MakeABitmap()
    Dim b As System.Drawing.Bitmap = Nothing
    Try
        b = New System.Drawing.Bitmap(100, 100)
        b.Save("c:\PrettyPicture.bmp")
    Catch ex As System.Security.SecurityException
        ' Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " & 
               "and the bitmap was not saved.")
    Catch ex As System.Exception
        ' React to other exceptions here.
        MessageBox.Show("Unable to create and save the bitmap.")
    End Try
End Sub
public void MakeABitmap()
{
    System.Drawing.Bitmap b = null;

    try
    {
        b = new System.Drawing.Bitmap(100, 100);
        b.Save("c:\\PrettyPicture.bmp");
    }
    catch (System.Security.SecurityException ex)
    {
        // Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " +
            "and the bitmap was not saved.");
    }
    catch (System.Exception ex)
    {
        // React to other exceptions here.
        MessageBox.Show("Unable to create and save the bitmap.");
    }
}

System.Security.Permissions 命名空间中的类、特性和枚举支持对应用程序中的安全任务提供更大的控制权。如果您要编写的库可以从其他应用程序调用,您将希望该库验证调用方代码是否具有相应的权限。例如,您可以在代码文件的顶部、AssemblyInfo.vb 文件或 AssemblyInfo.cs 文件中添加以下程序集级别的特性。有关更多信息,请参见 设置程序集特性

<Assembly: System.Security.Permissions.FileIOPermissionAttribute( 
    System.Security.Permissions.SecurityAction.RequestMinimum, 
    Write:="c:\PrettyPicture.bmp")> 
[assembly: System.Security.Permissions.FileIOPermissionAttribute(
    System.Security.Permissions.SecurityAction.RequestMinimum,
    Write = "c:\\PrettyPicture.bmp")]

加载程序集时,运行时会验证权限。如果运行时拒绝所请求的权限,将无法加载程序集,并引发安全性异常。如果将此特性添加至独立的应用程序中,该应用程序可能无法运行。如果类库中出现该特性,在运行时该库可能无法加载。需要在调用类库的代码中添加一个 try/catch 块。

还可以使用 Demand 方法专门用于从运行时请求权限,如下所示。随后运行时可能授予或拒绝该请求。如果拒绝该请求,将引发安全性异常。可以按照如下所示重写代码,以显式请求写入位图文件的权限:

Public Sub MakeABitmap()
    Dim b As System.Drawing.Bitmap = Nothing
    Dim filename = "c:\PrettyPicture.bmp"
    Dim permission As New System.Security.Permissions.FileIOPermission( 
        System.Security.Permissions.FileIOPermissionAccess.Write, 
        filename)

    Try
        permission.Demand()
        Try
            b = New System.Drawing.Bitmap(100, 100)
            b.Save(filename)
        Catch ex As System.Exception
            MessageBox.Show("Unable to create and save the bitmap.")
        End Try
    Catch ex As System.Security.SecurityException
        ' Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " & 
               "and the bitmap was not saved.")
    Catch ex As System.Exception
        ' React to other exceptions here.
        MessageBox.Show("Other error.")
    End Try
End Sub
public void MakeABitmap()
{
    System.Drawing.Bitmap b = null;
    string filename = "c:\\PrettyPicture.bmp";

    System.Security.Permissions.FileIOPermission permission;
    permission = new System.Security.Permissions.FileIOPermission(
        System.Security.Permissions.FileIOPermissionAccess.Write, filename);

    try
    {
        permission.Demand();
        try
        {
            b = new System.Drawing.Bitmap(100, 100);
            b.Save(filename);
        }
        catch (System.Exception ex)
        {
            MessageBox.Show("Unable to create and save the bitmap.");
        }
    }
    catch (System.Security.SecurityException ex)
    {
        // Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " +
               "and the bitmap was not saved.");
    }
    catch (System.Exception ex)
    {
        // React to other exceptions here.
        MessageBox.Show("Other error.");
    }
}

测试

在部分信任的区域中进行开发的第二步是在多个环境中进行测试,特别是在 Intranet 和 Internet 环境中。这样将强制引发安全性异常。一项重要的测试就是在本地计算机上创建不具备“管理员”权限的用户帐户,并尝试使用该帐户运行应用程序。

请参见

任务

如何:运行沙盒中部分受信任的代码

如何:通过使用 RequestMinimum 标志请求最小权限

概念

代码访问安全性

代码安全维护指南

.NET Framework 4 中的安全性更改