Applies to:SQL Server
托管数据库对象(如存储过程或触发器)先经过编译,然后部署到称为程序集的单元中。 必须先在 SQL Server 中注册托管 DLL 程序集,然后才能使用程序集提供的功能。 若要在 SQL Server 数据库中注册程序集,请使用 CREATE ASSEMBLY 语句。 本文讨论如何使用 CREATE ASSEMBLY 语句在数据库中注册程序集,以及如何指定程序集的安全设置。
不再支持代码访问安全性
CLR 在 .NET Framework 中使用代码访问安全性 (CAS)(不可再作为安全边界)。 使用 PERMISSION_SET = SAFE 创建的 CLR 程序集可以访问外部系统资源、调用非托管代码以及获取 sysadmin 特权。 在 SQL Server 2017 (14.x) 及更高版本中,sp_configure 选项 clr strict security 增强了 CLR 程序集的安全性。 默认启用 clr strict security,并将 SAFE 和 EXTERNAL_ACCESS 程序集与标记为 UNSAFE 的程序集同等对待。 可禁用 clr strict security 选项以实现后向兼容性,但不建议这样做。
我们建议所有程序集都通过证书或非对称密钥进行签名,且该证书或非对称密钥具有已在 UNSAFE ASSEMBLY 数据库中获得 master 权限的相应登录名。 SQL Server 管理员还可以将程序集添加到数据库引擎应信任的程序集列表。 For more information, see sys.sp_add_trusted_assembly.
CREATE ASSEMBLY 语句
CREATE ASSEMBLY 语句用于在数据库中创建程序集。 下面是一个示例:
CREATE ASSEMBLY SQLCLRTest
FROM 'C:\MyDBApp\SQLCLRTest.dll';
FROM 子句指定要创建的程序集的路径名称。 此路径既可以是通用命名约定 (UNC) 路径,也可以是计算机本地的物理文件路径。
SQL Server 不允许使用同一名称、区域性和公钥注册不同版本的程序集。
可以创建引用其他程序集的程序集。 在 SQL Server 中创建程序集时,如果尚未将引用的程序集创建到数据库中,SQL Server 还会创建根级程序集引用的程序集。
数据库用户或用户角色有权在数据库中创建因此拥有程序集。 若要创建程序集,数据库用户或角色应具有 CREATE ASSEMBLY 权限。
仅当满足以下条件时,程序集才能成功地引用其他程序集:
- 调用或引用的程序集由同一用户或角色拥有。
- 调用或引用的程序集是在同一数据库中创建的。
创建程序集时指定安全性
在 SQL Server 数据库中创建程序集时,可以指定以下三种不同级别的安全级别之一:SAFE、EXTERNAL_ACCESS或 UNSAFE。 运行 CREATE ASSEMBLY 语句时,对代码程序集执行某些检查,这可能会导致程序集无法在服务器上注册。
SAFE 是默认权限集,适用于大多数方案。 若要指定给定的安全级别,请修改 CREATE ASSEMBLY 语句的语法,如下所示:
CREATE ASSEMBLY SQLCLRTest
FROM 'C:\MyDBApp\SQLCLRTest.dll'
WITH PERMISSION_SET = SAFE;
还可以通过省略上一行的权限集创建具有 SAFE 权限集的程序集。
CREATE ASSEMBLY SQLCLRTest
FROM 'C:\MyDBApp\SQLCLRTest.dll';
当程序集中的代码在 SAFE 权限集下运行时,它只能通过进程内托管提供程序在服务器中执行计算和数据访问。
创建EXTERNAL_ACCESS和 UNSAFE 程序集
EXTERNAL_ACCESS 解决了代码需要访问服务器外部的资源(例如文件、网络、注册表和环境变量)的方案。 只要服务器访问外部资源,它就会模拟调用托管代码的用户的安全上下文。
UNSAFE 代码权限适用于程序集无法验证安全或需要对受限资源(如 Win32 API)的其他访问权限的情况。
若要在 SQL Server 中创建 EXTERNAL_ACCESS 或 UNSAFE 程序集,必须满足以下两个条件之一:
程序集经过了强名称签名或使用证书进行了 Authenticode 签名。 此强名称(或证书)在 SQL Server 内部创建为非对称密钥(或证书),并具有具有
EXTERNAL ACCESS ASSEMBLY权限(对于外部访问程序集)或UNSAFE ASSEMBLY权限(对于不安全程序集)的相应登录名。数据库所有者(DBO)具有
EXTERNAL ACCESS ASSEMBLY(对于EXTERNAL ACCESS程序集)或UNSAFE ASSEMBLY(对于UNSAFE程序集)权限,数据库具有 TRUSTWORTHY 数据库属性 设置为ON。
前面列出的两个条件也会在程序集加载时(包括执行)进行检查。 至少必须满足这些条件之一才能加载程序集。
建议数据库上的 TRUSTWORTHY 数据库属性 未设置为 ON 仅在服务器进程中运行公共语言运行时 (CLR) 代码。 相反,我们建议从 master 数据库中的程序集文件创建非对称密钥。 然后必须创建映射到此非对称密钥的登录名,并且必须向该登录名授予 EXTERNAL ACCESS ASSEMBLY 或 UNSAFE ASSEMBLY 权限。
以下 Transact-SQL 语句执行创建非对称密钥所需的步骤,将登录名映射到此密钥,然后向该登录名授予 EXTERNAL_ACCESS 权限。 在运行 CREATE ASSEMBLY 语句之前,必须运行以下 Transact-SQL 语句。
USE master;
GO
CREATE ASYMMETRIC KEY SQLCLRTestKey
FROM EXECUTABLE FILE = 'C:\MyDBApp\SQLCLRTest.dll';
CREATE LOGIN SQLCLRTestLogin
FROM ASYMMETRIC KEY SQLCLRTestKey;
GRANT EXTERNAL ACCESS ASSEMBLY TO SQLCLRTestLogin;
GO
Note
必须创建新的登录名以与非对称密钥关联。 此登录名仅用于授予权限。 它不必与用户关联,也不必在应用程序中使用。
若要创建 EXTERNAL ACCESS 程序集,创建者需要在创建程序集时指定 EXTERNAL ACCESS 权限:
CREATE ASSEMBLY SQLCLRTest
FROM 'C:\MyDBApp\SQLCLRTest.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
以下 Transact-SQL 语句执行创建非对称密钥所需的步骤,将登录名映射到此密钥,然后向该登录名授予 UNSAFE 权限。 在运行 CREATE ASSEMBLY 语句之前,必须运行以下 Transact-SQL 语句。
USE master;
GO
CREATE ASYMMETRIC KEY SQLCLRTestKey
FROM EXECUTABLE FILE = 'C:\MyDBApp\SQLCLRTest.dll';
CREATE LOGIN SQLCLRTestLogin
FROM ASYMMETRIC KEY SQLCLRTestKey;
GRANT UNSAFE ASSEMBLY TO SQLCLRTestLogin;
GO
若要指定具有 UNSAFE 权限的程序集加载,请在将程序集加载到服务器时指定 UNSAFE 权限集:
CREATE ASSEMBLY SQLCLRTest
FROM 'C:\MyDBApp\SQLCLRTest.dll'
WITH PERMISSION_SET = UNSAFE;
有关每个设置的权限的详细信息,请参阅 CLR 集成安全性。