65.9K
CodeProject 正在变化。 阅读更多。
Home

SQL Server 2005 报表服务中的自定义程序集

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.25/5 (9投票s)

2005年8月26日

7分钟阅读

viewsIcon

76556

本文重点介绍了在使用 .NET 自定义程序集时可能遇到的问题及可能的解决方案。本文还详细介绍了修改您没有源代码的 .NET 程序集的细节。

引言

在 SQL Server 报表服务中,您可以使用自定义程序集,它允许您使用您选择的任何语言为报表添加更多功能。这可以通过在报表设计器的“报表属性 - > 引用”窗口中引用自定义程序集来完成。本文重点介绍了在使用 .NET 自定义程序集时可能遇到的问题及可能的解决方案。本文还详细介绍了修改您没有源代码的 .NET 程序集的细节。

报表服务器和报表设计器如何与自定义程序集协同工作

首先,让我们了解一下“报表服务器”和“报表设计器”是如何调用自定义程序集中的函数的。

“报表服务器”在报表部署到服务器运行后调用自定义程序集中的函数。CLR 使用与处理 .NET 应用程序时相同的方法来加载外部程序集。要让 CLR 成功加载,必须将报表中使用的自定义程序集放置在“C:\Program Files\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer\bin”位置。而对于报表设计器,则需要将程序集放置在“C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies”位置,这是“报表设计器” IDE 的本地目录。

SQL Server 报表服务使用“代码访问安全”来限制自定义代码使用服务器资源。“报表设计器”和“报表服务器”运行报表的安全模型是不同的。“报表设计器”以完全信任安全级别运行自定义程序集,因此在预览报表时您可能不会遇到安全相关的问题。在“报表服务器”中,默认情况下,自定义代码以有限的执行权限运行,具体由 rssrvpolicy.config 文件指定。自定义代码将由“报表表达式主机程序集”调用,该程序集以有限的“执行”权限运行。“执行”权限集允许代码运行,但不能使用受保护的资源。即使从该程序集中调用的任何代码被授予了“完全信任”,它们也以“执行”权限运行。这是因为 CLR 会验证调用堆栈层次结构中所有程序集的安全性。如果其中任何一个程序集被授予的权限较少,则调用将以安全权限异常终止。(但是,您可以使用后续章节中讨论的 Security.Assert 功能来覆盖此行为)。在某些情况下,您可能需要在自定义程序集中实现适当的安全调用来保护资源。

注意:“报表服务器”使用 rssrvpolicy.config 文件设置中的安全权限集来应用“代码访问安全”;它不使用通过 .NET “框架配置 MMC 管理单元”设置的 .NET 安全配置文件。

自定义程序集的类型

让我们探讨一下我们在报表中使用过的不同自定义程序集,它们在不同场景下会引发不同的问题。下面讨论了几种场景:

  • 您可以编写自己的 .NET 程序集并在报表中使用。(如果您使用的是带有源代码的第三方 .NET 组件,则属于此类)。
  • 您可以使用第三方 COM 组件的 .NET 互操作程序集。(如果您使用的是第三方 .NET 组件但没有源代码,则属于此类)。

使用您自己的 .NET 程序集

您可以编写带有源代码的自定义程序集并在报表中使用,以利用某些特定语言的功能。.NET 程序集可以是私有的,也可以是签名的,以便从 GAC(.NET 全局程序集缓存)中使用。.NET 程序集无需签名即可在报表中使用。但是,如果您使用签名程序集,则需要用 AllowPartiallyTrustedCallersAttribute 标记自定义程序集。这是必需的,因为自定义程序集是从报表表达式中调用的,而报表表达式是“报表表达式主机程序集”的一部分,该程序集未被授予**完全信任**,是一个“部分信任”的调用方。您可以修改策略配置文件以授予您的程序集特定权限。为了让您的代码获得适当的权限,您必须在自定义程序集代码中断言该权限。例如,假设一个方法正在访问系统中的特定资源,您可以为此方法标记以下安全属性:

  • [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)] 或您可以指定您需要的权限。(这可以通过在程序集的所需方法中编写与安全相关的代码来实现)。

为了让“报表服务器”和“报表设计器”成功加载程序集,需要将其放置在前面章节指定的文件夹中。您还需要在 rssrvpolicy.config 文件中为上述创建的自定义程序集创建一个代码组。您可以通过将以下 XML 复制并粘贴到 CONFIG 文件中的适当位置来完成此操作。

<CodeGroup
    class="UnionCodeGroup"
    version="1"
    PermissionSetName="FullTrust"
    Name="MyCustomAssembly"
    Description=
      "This group grants full permission for my custom assemblies">
    <IMembershipCondition
        class="StrongNameMembershipCondition"
        version="1.0.0.0"
        PublicKeyBlob="Your public key blob"/>
</CodeGroup>

对于未签名的程序集,您需要创建具有 URL 成员身份 XML 的代码组,并将其添加到 rssrvpolicy.config 文件中,如下所示:

<CodeGroup
    class="UnionCodeGroup"
    version="1"
    PermissionSetName="FullTrust"
    Name="MyCustomAssembly"
    Description=
       "This group grants full permission for my custom assemblies ">
    <IMembershipCondition
        class="UrlMembershipCondition"
        version="1.0.0.0"
        URL="Your custom assmbly path"/>
</CodeGroup>

使用来自第三方 COM 组件的 .NET 互操作程序集

您还可以使用报表中的 .NET 互操作程序集来利用第三方 COM 组件的功能。这种情况非常棘手,您可能对方法的内部实现知之甚少,因此很难授予程序集特定的权限集。因此,来自此程序集的任何资源访问都需要“报表表达式主机程序集”在 rssrvpolicy.config 文件中获得“完全信任”权限,这在 Internet 报表应用程序中可能存在风险。任何使用“表达式主机”在“报表服务器”上以“完全信任”运行的恶意代码,都可能导致您的“报表服务器”崩溃。

因此,解决此问题的一种方法是对此互操作程序集进行签名,并向程序集添加 AllowPartiallyTrustedCallers 属性,并为特定方法授予适当的安全权限。这是一项非常繁琐的任务,因为您可能没有组件的源代码来应用所需的属性/代码。有趣的是,您可以通过操作所需程序集的 MSIL 来实现这一点。这需要 .NET 工具和技术知识。如果您有兴趣这样做,请按照以下步骤操作:

步骤 1:为您的 COM 创建 .NET 互操作程序集,您还需要在其中指定强名称密钥文件(您可以使用 sn.exe .NET 工具创建密钥文件),以便获得签名程序集。

步骤 2:使用 ILDASM.exe .NET 工具获取程序集的 IL 代码。(您需要使用此工具打开程序集并使用转储功能获取 MSIL)。

步骤 3:将 AllowPartiallyTrustedCallers 属性添加到 MSIL 代码。这可以通过将以下 MSIL 代码行复制到 .assembly YourAssembly 部分中来完成。

[编辑者注:使用换行符避免滚动]

.custom instance void 
   [mscorlib]System.Security.AllowPartiallyTrustedCallersAttribute::.ctor() = 
                                                                ( 01 00 00 00 )

步骤 4:将 assert 安全属性添加到需要调用以访问资源的那些方法。您可以通过将以下 MSIL 代码复制到要访问的每个方法中来完成此操作:

.permissionset assert = 
    (3C 00 50 00 65 00 72 00 6D 00 69 00 73 00 73 00 // <.P.e.r.m.i.s.s.
    69 00 6F 00 6E 00 53 00 65 00 74 00 20 00 63 00 // i.o.n.S.e.t. .c.
    6C 00 61 00 73 00 73 00 3D 00 22 00 53 00 79 00 // l.a.s.s.=.".S.y.
    73 00 74 00 65 00 6D 00 2E 00 53 00 65 00 63 00 // s.t.e.m...S.e.c.
    75 00 72 00 69 00 74 00 79 00 2E 00 50 00 65 00 // u.r.i.t.y...P.e.
    72 00 6D 00 69 00 73 00 73 00 69 00 6F 00 6E 00 // r.m.i.s.s.i.o.n.
    53 00 65 00 74 00 22 00 0D 00 0A 00 20 00 20 00 // S.e.t."..... . .
    20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 // . . . . . . . .
    20 00 20 00 20 00 20 00 20 00 76 00 65 00 72 00 // . . . . .v.e.r.
    73 00 69 00 6F 00 6E 00 3D 00 22 00 31 00 22 00 // s.i.o.n.=.".1.".
    0D 00 0A 00 20 00 20 00 20 00 20 00 20 00 20 00 // .... . . . . . .
    20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 // . . . . . . . .
    20 00 55 00 6E 00 72 00 65 00 73 00 74 00 72 00 // .U.n.r.e.s.t.r.
    69 00 63 00 74 00 65 00 64 00 3D 00 22 00 74 00 // i.c.t.e.d.=.".t.
    72 00 75 00 65 00 22 00 2F 00 3E 00 0D 00 0A 00 ) // r.u.e."./.>.....

步骤 5:使用 ilasm.exe .NET 工具编译 MSIL 代码。您可以使用命令 ilasm /dll yourilcodefile.il 来完成此操作。

步骤 6:获得 DLL 后,您需要重新签名程序集以重新计算哈希。您可以通过使用 sn.exe .NET 工具并指定 –R 开关以及 DLL 和密钥文件来完成此操作。

步骤 7:将程序集安装到 .NET 全局程序集缓存中。您可以通过将程序集拖放到 C:\Windows\Assembly 文件夹中来完成此操作。您还需要将文件复制到我在本文开头指定的文件夹中,以便它能够在“报表服务器”和“报表设计器”中正常工作。

步骤 8:您还需要在 rssrvpolicy.config 文件中为上述创建的文件创建一个代码组。您可以通过将以下 XML 复制并粘贴到适当位置的 config 文件中来完成此操作。

<CodeGroup
    class="UnionCodeGroup"
    version="1"
    PermissionSetName="FullTrust"
    Name="MyCustomAssembly"
    Description=
      "This group grants full permission for my custom assmeblies ">
    <IMembershipCondition
        class="StrongNameMembershipCondition"
        version="1.0.0.0"
        PublicKeyBlob="Your public key blob"/>
</CodeGroup>

注意:在处理 XML 配置文件时要小心。确保其格式正确,可以在 Internet Explorer 中打开进行检查。现在,您可以转到 SQL Server 报表服务 Web 环境中运行您的报表,并合法地使用服务器资源。

这种 MSIL 修改技术还可以用于您没有源代码的 .NET 程序集以及任何其他需要程序集操作的 .NET 要求。正如我之前提到的,这需要对 MSIL 和 .NET 工具非常了解。

摘要

本文详细介绍了“报表服务器”和“报表设计器”的内部工作原理,以便深入了解与安全相关的问题。它还介绍了如何在没有源代码的情况下修改 .NET 程序集,以添加一些特殊属性,这有助于在报表服务以及任何需要程序集修改的 .NET 应用程序开发场景中使用自定义程序集。

© . All rights reserved.