Service Broker 对话安全设置

对话安全设置可以为特定会话提供加密、远程身份验证和远程授权。会话使用对话安全设置时,Service Broker 将加密发送到 SQL Server 实例外部的所有消息。默认情况下,Service Broker 会话使用对话安全设置。

对话安全设置基础

利用 Service Broker 对话安全设置,应用程序可以对单个对话会话(或对话)进行身份验证、授权或加密。默认情况下,所有对话会话均使用对话安全设置。开始对话时,在 BEGIN DIALOG CONVERSATION 语句中包含 ENCRYPTION = OFF 子句,可以显式允许对话在不使用对话安全设置的情况下进行。但是,如果存在会话目标服务的远程服务绑定,则即使在 ENCRYPTION = OFF 的情况下,对话也使用对话安全设置。

对于使用对话安全设置的对话,Service Broker 将对发送到 SQL Server 实例外部的所有消息进行加密。保留在 SQL Server 实例中的消息从不加密。在对话安全设置中,仅作为起始服务宿主的数据库和作为目标服务宿主的数据库才需要能够访问用于提供安全性的证书。即执行消息转发的实例无需具备解密实例所转发消息的功能。

Service Broker 提供两种类型的对话安全设置,“完全安全设置”和“匿名安全设置”。对于使用对话安全设置的会话,Service Broker 提供远程授权,将会话的远程端映射到本地用户。

无论会话使用完全安全设置还是匿名安全设置,消息都要在网络上进行加密。但是,在这两种方法之间,目标数据库中的有效权限和用于消息加密的策略略有不同。

无论会话使用完全安全设置还是使用匿名安全设置,消息正文都使用为特定会话生成的对称会话密钥进行加密。只有密钥才使用私钥加密算法进行加密,该私钥加密算法使用对话安全设置提供的证书。Service Broker 还执行消息完整性检查,以帮助检测消息是否已损坏或被篡改。

SQL Server 为使用对话安全设置的会话创建会话密钥。为了保护存储在数据库中的会话密钥,Service Broker 用数据库的主密钥对会话密钥进行加密。如果数据库主密钥不可用,则会话消息仍处于 transmission_status 状态并返回一个错误,直到创建数据库主密钥,或会话超时为止。因此,参与会话的两个数据库都必须包含主密钥,即使这两个数据库在同一实例中时亦如此。如果起始数据库不包含主密钥,则对话将失败。如果目标数据库不包含主密钥,则消息将保存在起始数据库的传输队列中。这些消息的最后一个传输错误指示无法传递这些消息的原因。使用 ENCRYPTION = OFF 参数创建未加密对话,或使用下列命令创建数据库主密钥:

CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<password>'

为方便起见,Service Broker 允许停留在单个数据库中的安全会话继续进行,而不考虑该数据库是否包含主密钥。虽然两个不同的数据库可以在会话生存期期间移到不同的 SQL Server 实例中,但是单个数据库中的会话将始终停留在该数据库中。因此,会话可以进行。

完全安全设置

完全安全设置帮助防止起始服务向不可信数据库发送消息,并帮助防止目标服务接收来自不可信数据库的消息。会话使用完全安全设置时,Service Broker 对通过网络传输的消息进行加密。

完全安全设置为起始服务和目标服务均提供标识。完全安全设置要求起始服务信任目标服务,并且目标服务也信任起始服务。例如,从供应商订购零件的服务可能要求订购应用程序信任供应商服务,并且供应商服务也信任订购应用程序。

数据库管理员通过交换包含公钥的证书建立信任。对于完全对话安全设置,每一会话端都包含本地用户的私钥和远程用户的公钥。作为起始服务宿主的数据库包含“远程服务绑定”。远程服务绑定指定拥有与远程数据库中的私钥相对应的证书的本地用户。因此,代表起始服务的操作将在目标数据库中以指定的用户身份运行。

目标数据库包含相应的用户。此用户拥有与发起起始服务的用户所拥有的私钥相对应的证书。因此,代表目标服务的操作在起始数据库中以发起起始服务的用户身份运行。

对于使用完全安全设置的对话,每一会话端都生成一个会话密钥。每个方向中的第一条消息均包含会话密钥,它用密钥交换密钥进行加密,详细信息请参阅证书和 Service Broker

匿名安全设置

匿名安全设置帮助防止起始服务将消息发送到不可信数据库。会话使用匿名安全设置时,Service Broker 对通过网络传输的消息进行加密。

匿名安全设置标识相对于起始服务的目标服务,但不标识相对于目标服务的起始服务。

例如,提交工作通知单的应用程序可能需要保证工作通知单的接收人是预期接收人,但目标数据库可能不需要提供有关提交工作通知单的服务的任何特权。在这种情况下,包含起始服务的数据库必须包含针对目标服务的远程服务绑定。

由于目标服务无法验证起始服务的标识,因此代表起始服务的操作在目标数据库中以固定数据库角色 public 的成员身份运行。目标数据库接收不到有关启动该会话的用户的任何信息。目标数据库无需包含启动该会话的用户的证书。

对于使用匿名安全设置的对话,会话两端均使用由起始数据库生成的会话密钥。目标数据库不向起始数据库返回会话密钥。

对话安全设置的安全上下文

Service Broker 远程授权控制对单个服务的远程访问。远程授权确定安全上下文,SQL Server 实例的传入消息在此上下文中发送到服务。

对于不完全在一个 SQL Server 实例中发生的安全会话,Service Broker 将始终使用远程授权。为会话配置的对话安全设置确定 Service Broker 用于进行远程授权的安全上下文。

会话停留在一个 SQL Server 实例中时,即使已配置了远程授权,Service Broker 也不使用远程授权。对于停留在一个实例中的会话,SQL Server 中已有 SQL Server 安全主体,因此无需使用远程授权来确定 Service Broker 操作的正确安全上下文。但是,正如本主题前面所述,Service Broker 创建会话密钥,以便在会话期间将某个数据库移到另一个实例中时,会话仍可继续进行。

对于使用匿名安全设置的会话,连接在目标数据库中以固定数据库角色 public 的成员身份运行。在这种情况下,固定数据库角色 public 必须具有向服务发送消息的权限。但该角色无需数据库中的其他权限。

对于使用完全安全设置的会话,各会话端的连接在运行时具有远程服务绑定中指定的用户的权限。例如,如果远程服务绑定将服务名称 InventoryService 与用户 InventoryServiceRemoteUser 关联在一起,则 SQL Server 将使用 InventoryServiceRemoteUser 的安全上下文将 InventoryService 应用程序的消息放到目标服务的队列中。

为提高安全性,拥有服务私钥的用户通常与被指定激活的用户不同。拥有私钥的用户只需要向队列中添加消息的权限,即针对使用该队列的服务的 SEND 权限。相反,被指定激活的用户应具有完成请求的工作及发送响应所需的权限。在上一示例中,InventoryServiceRemoteUser 不需要查询库存表和发送返回消息的权限。用户只需要向 InventoryService 所使用的队列发送消息的权限。存储过程激活发生在具有队列所指定的凭据的另一个会话中。在将消息排入队列的会话与处理消息的会话之间不需要共享凭据。

创建安全对话

Service Broker 建立两个数据库之间的对话时,起始服务必须在目标数据库中建立用户上下文,以便将消息放置于目标队列中。此用户上下文确定起始服务是否有权限打开与目标数据库的对话。

实现此操作的最佳方法是创建证书和远程服务绑定。有关创建证书的详细信息,请参阅 CREATE CERTIFICATE (Transact-SQL)。有关创建远程服务绑定的详细信息,请参阅 CREATE REMOTE SERVICE BINDING (Transact-SQL)

创建证书和远程服务绑定的另一方法是使用 SQL Server 安全模型建立两个数据库之间的信任关系。起始服务的所有者将模拟目标服务中的用户。这可能会要求将起始数据库的 TRUSTWORTHY 数据库属性设置为“打开”,并且对目标数据库中的用户授予身份验证时所需的权限。有关详细信息,请参阅使用 EXECUTE AS 扩展数据库模拟

注意注意

如果安全上下文的设置不正确,则对话框中发送的消息将保留在起始服务的 sys.transmission_queue 中,并且在 transmission_status 列中出现以下错误消息:“主体服务器 '%.*ls' 无法访问当前安全上下文中的数据库 '%.*ls'”