使用共享访问签名进行服务总线访问控制Service Bus access control with Shared Access Signatures

本文介绍共享访问签名 (SAS)、其工作原理以及如何以平台无关的方式使用它们。This article discusses Shared Access Signatures (SAS), how they work, and how to use them in a platform-agnostic way.

SAS 可以根据授权规则来保护对服务总线的访问。SAS guards access to Service Bus based on authorization rules. 可以在命名空间或消息传递实体(队列或主题)中配置这些保护。Those are configured either on a namespace, or a messaging entity (queue, or topic). 授权规则具有与特定权限关联的名称,并包含一个加密密钥对。An authorization rule has a name, is associated with specific rights, and carries a pair of cryptographic keys. 通过服务总线 SDK 或者在自己的代码中使用规则名称和密钥可以生成 SAS 令牌。You use the rule's name and key via the Service Bus SDK or in your own code to generate a SAS token. 然后,客户端可将令牌传递给服务总线,以证明请求的操作获得授权。A client can then pass the token to Service Bus to prove authorization for the requested operation.


Azure 服务总线支持使用 Azure Active Directory (Azure AD) 授予对服务总线命名空间及其实体的访问权限。Azure Service Bus supports authorizing access to a Service Bus namespace and its entities using Azure Active Directory (Azure AD). 使用 Azure AD 返回的 OAuth 2.0 令牌授权用户或应用程序可提供比共享访问签名 (SAS) 更高的安全性和易用性。Authorizing users or applications using OAuth 2.0 token returned by Azure AD provides superior security and ease of use over shared access signatures (SAS). 使用 Azure AD,不需要在代码中存储令牌,也不需要冒潜在的安全漏洞风险。With Azure AD, there is no need to store the tokens in your code and risk potential security vulnerabilities.

Azure 建议尽量对 Azure 服务总线应用程序使用 Azure AD。Azure recommends using Azure AD with your Azure Service Bus applications when possible. 有关详细信息,请参阅以下文章:For more information, see the following articles:

SAS 概述Overview of SAS

共享访问签名是使用简单令牌的基于声明的授权机制。Shared Access Signatures are a claims-based authorization mechanism using simple tokens. 使用 SAS 时,永远不会通过网络传递密钥。Using SAS, keys are never passed on the wire. 密钥用于以加密方式将信息签名,以后,服务可以验证这些信息。Keys are used to cryptographically sign information that can later be verified by the service. 可以像使用用户名和密码一样使用 SAS。在用户名和密码方案中,客户端直接拥有授权规则名称和匹配的密钥。SAS can be used similar to a username and password scheme where the client is in immediate possession of an authorization rule name and a matching key. 此外,还可以像在联合安全模型中一样使用 SAS。在此模型中,客户端从安全令牌服务接收限时且经过签名的访问令牌,而无需拥有签名密钥。SAS can also be used similar to a federated security model, where the client receives a time-limited and signed access token from a security token service without ever coming into possession of the signing key.

服务总线中的 SAS 身份验证配置了指定的共享访问授权规则,这些规则具有关联的访问权限,以及一对主要和辅助加密密钥。SAS authentication in Service Bus is configured with named Shared Access Authorization Rules having associated access rights, and a pair of primary and secondary cryptographic keys. 密钥是采用 Base64 表示法的 256 位值。The keys are 256-bit values in Base64 representation. 在服务总线的中继队列主题中,可以在命名空间级别配置规则。You can configure rules at the namespace level, on Service Bus relays, queues, and topics.

共享访问签名令牌包含所选授权规则的名称、应访问的资源的 URI、即时过期时间,以及使用所选授权规则的主要或辅助加密密钥基于这些字段计算的 HMAC-SHA256 加密签名。The Shared Access Signature token contains the name of the chosen authorization rule, the URI of the resource that shall be accessed, an expiry instant, and an HMAC-SHA256 cryptographic signature computed over these fields using either the primary or the secondary cryptographic key of the chosen authorization rule.

共享访问授权策略Shared Access Authorization Policies

每个服务总线命名空间和服务总线实体都有一个由规则构成的共享访问授权策略。Each Service Bus namespace and each Service Bus entity has a Shared Access Authorization policy made up of rules. 命名空间级别的策略应用到该命名空间中的所有实体,不管这些实体各自的策略配置如何。The policy at the namespace level applies to all entities inside the namespace, irrespective of their individual policy configuration.

对于每个授权策略规则,需要确定三个信息片段:名称范围权限For each authorization policy rule, you decide on three pieces of information: name, scope, and rights. 名称 只是该范围内的唯一名称。The name is just that; a unique name within that scope. 范围也很简单:它是相关资源的 URI。The scope is easy enough: it's the URI of the resource in question. 对于服务总线命名空间,范围是完全限定的域名 (FQDN),例如 https://<yournamespace>.servicebus.chinacloudapi.cn/For a Service Bus namespace, the scope is the fully qualified domain name (FQDN), such as https://<yournamespace>.servicebus.chinacloudapi.cn/.

策略规则授予的权限可以是以下各项的组合:The rights conferred by the policy rule can be a combination of:

  • “发送”- 授予向实体发送消息的权限'Send' - Confers the right to send messages to the entity
  • “侦听”- 授予接收(队列、订阅)和所有相关消息处理的权限'Listen' - Confers the right to receive (queue, subscriptions) and all related message handling
  • “管理”- 授予管理命名空间的拓扑的权限,包括创建和删除实体'Manage' - Confers the right to manage the topology of the namespace, including creating and deleting entities

“管理”权限包括“发送”和“接收”权限。The 'Manage' right includes the 'Send' and 'Receive' rights.

一个命名空间或实体策略最多可以包含 12 个共享访问授权规则,为三组规则提供空间。其中每个规则涵盖了基本权限,以及“发送”和“侦听”权限的组合。A namespace or entity policy can hold up to 12 Shared Access Authorization rules, providing room for three sets of rules, each covering the basic rights and the combination of Send and Listen. 根据此项限制,很明显 SAS 策略存储并不适合用作用户或服务帐户存储。This limit underlines that the SAS policy store is not intended to be a user or service account store. 如果应用程序需要根据用户或服务标识授予服务总线的访问权限,应实现安全令牌服务,以便在执行身份验证和访问检查后颁发 SAS 令牌。If your application needs to grant access to Service Bus based on user or service identities, it should implement a security token service that issues SAS tokens after an authentication and access check.

将为授权规则分配主要密钥和辅助密钥。 An authorization rule is assigned a Primary Key and a Secondary Key. 它们是加密形式的强密钥。These are cryptographically strong keys. 请不要遗失或透漏这些密钥 - 在 Azure 门户中总要用到它们。Don't lose them or leak them - they'll always be available in the Azure portal. 可以使用其中一个生成的密钥,并且随时可以重新生成密钥。You can use either of the generated keys, and you can regenerate them at any time. 如果重新生成或更改策略中的密钥,以前基于该密钥颁发的所有令牌会立即失效。If you regenerate or change a key in the policy, all previously issued tokens based on that key become instantly invalid. 但是,基于此类令牌创建的现有连接将继续工作,直到该令牌过期。However, ongoing connections created based on such tokens will continue to work until the token expires.

创建服务总线命名空间时,系统会自动为该命名空间创建名为 RootManageSharedAccessKey 的策略规则。When you create a Service Bus namespace, a policy rule named RootManageSharedAccessKey is automatically created for the namespace. 此策略具有整个命名空间的“管理”权限。This policy has Manage permissions for the entire namespace. 建议将此规则视为 root 管理帐户,且不要在应用程序中使用它。It's recommended that you treat this rule like an administrative root account and don't use it in your application. 可以通过门户上命名空间的“配置”选项卡、PowerShell 或 Azure CLI 创建更多策略规则。You can create additional policy rules in the Configure tab for the namespace in the portal, via PowerShell or Azure CLI.

使用 SAS 的最佳实践Best practices when using SAS

在应用程序中使用共享访问签名时,需要知道以下两个可能的风险:When you use shared access signatures in your applications, you need to be aware of two potential risks:

  • 如果 SAS 泄露,则获取它的任何人都可以使用它,这可能会使服务总线资源遭到入侵。If a SAS is leaked, it can be used by anyone who obtains it, which can potentially compromise your Service Bus resources.
  • 如果提供给客户端应用程序的 SAS 到期并且应用程序无法从服务检索新 SAS,则可能会影响该应用程序的功能。If a SAS provided to a client application expires and the application is unable to retrieve a new SAS from your service, then application's functionality may be hindered.

下面这些针对使用共享访问签名的建议可帮助降低这些风险:The following recommendations for using shared access signatures can help mitigate these risks:

  • 如果需要,让客户端自动续订 SAS:客户端应在到期时间之前很久就续订 SAS,这样,即使提供 SAS 的服务不可用,客户端也有时间重试。Have clients automatically renew the SAS if necessary: Clients should renew the SAS well before expiration, to allow time for retries if the service providing the SAS is unavailable. 如果 SAS 旨在用于少量即时的短期操作,这些操作应在到期时间内完成,则上述做法可能是不必要的,因为不应续订 SAS。If your SAS is meant to be used for a small number of immediate, short-lived operations that are expected to be completed within the expiration period, then it may be unnecessary as the SAS is not expected to be renewed. 但是,如果客户端定期通过 SAS 发出请求,则有效期可能就会起作用。However, if you have client that is routinely making requests via SAS, then the possibility of expiration comes into play. 需要考虑的主要方面就是在以下两者间进行权衡:对短期 SAS 的需求(如前文所述)以及确保客户端尽早请求续订(以免在成功续订前因 SAS 到期而中断)。The key consideration is to balance the need for the SAS to be short-lived (as previously stated) with the need to ensure that client is requesting renewal early enough (to avoid disruption due to the SAS expiring prior to a successful renewal).
  • 要注意 SAS 开始时间:如果将 SAS 的开始时间设置为“现在”,则由于时钟偏移(根据不同计算机,当前时间的差异),在前几分钟将会间歇地观察到失败。Be careful with the SAS start time: If you set the start time for SAS to now, then due to clock skew (differences in current time according to different machines), failures may be observed intermittently for the first few minutes. 通常,将开始时间至少设置为 15 分钟前。In general, set the start time to be at least 15 minutes in the past. 或者根本不设置,这会使它在所有情况下都立即生效。Or, don't set it at all, which will make it valid immediately in all cases. 同样的原则也适用于过期时间。The same generally applies to the expiry time as well. 请记住,对于任何请求,在任一方向你可能会观察到最多 15 分钟的时钟偏移。Remember that you may observer up to 15 minutes of clock skew in either direction on any request.
  • 对要访问的资源要具体:一种安全性最佳做法是向用户提供所需最小权限。Be specific with the resource to be accessed: A security best practice is to provide user with the minimum required privileges. 如果某一用户仅需要对单个实体的读取访问权限,则向该用户授予对该单个实体的读取访问权限,而不要授予针对所有实体的读取/写入/删除访问权限。If a user only needs read access to a single entity, then grant them read access to that single entity, and not read/write/delete access to all entities. 如果 SAS 泄露,这也有助于降低损失,因为攻击者手中掌握的 SAS 的权限较为有限。It also helps lessen the damage if a SAS is compromised because the SAS has less power in the hands of an attacker.
  • 不要总是使用 SAS:有时,与针对事件中心的特定操作相关联的风险要超过 SAS 所带来的好处。Don't always use SAS: Sometimes the risks associated with a particular operation against your Event Hubs outweigh the benefits of SAS. 对于此类操作,应创建一个中间层服务,该服务在执行业务规则验证、身份验证和审核后写入事件中心。For such operations, create a middle-tier service that writes to your Event Hubs after business rule validation, authentication, and auditing.
  • 始终使用 HTTPs:始终使用 HTTPs 创建或分发 SAS。Always use HTTPs: Always use Https to create or distribute a SAS. 如果某一 SAS 通过 HTTP 传递并且被截取,则执行中间人攻击的攻击者将能够读取 SAS、并使用它,就像目标用户本可执行的操作一样,这可能会暴露敏感数据或者使恶意用户能够损坏数据。If a SAS is passed over HTTP and intercepted, an attacker performing a man-in-the-middle attach is able to read the SAS and then use it just as the intended user could have, potentially compromising sensitive data or allowing for data corruption by the malicious user.

共享访问签名身份验证的配置Configuration for Shared Access Signature authentication

可在服务总线命名空间、队列或主题上配置 SharedAccessAuthorizationRule 规则。You can configure the SharedAccessAuthorizationRule rule on Service Bus namespaces, queues, or topics. 当前不支持在服务总线订阅上配置 SharedAccessAuthorizationRule,但是可以使用命名空间或主题上配置的规则来确保安全访问订阅。Configuring a SharedAccessAuthorizationRule on a Service Bus subscription is currently not supported, but you can use rules configured on a namespace or topic to secure access to subscriptions. 有关说明此过程的工作示例,请参阅 Using Shared Access Signature (SAS) authentication with Service Bus Subscriptions(将共享访问签名 (SAS) 身份验证与服务总线订阅配合使用)示例。For a working sample that illustrates this procedure, see the Using Shared Access Signature (SAS) authentication with Service Bus Subscriptions sample.


在此图中,manageRuleNS、sendRuleNS 和 listenRuleNS 授权规则适用于队列 Q1 和主题 T1,而 listenRuleQ 和 sendRuleQ 仅适用于队列 Q1,sendRuleT 仅适用于主题 T1。In this figure, the manageRuleNS, sendRuleNS, and listenRuleNS authorization rules apply to both queue Q1 and topic T1, while listenRuleQ and sendRuleQ apply only to queue Q1 and sendRuleT applies only to topic T1.

生成共享访问签名令牌Generate a Shared Access Signature token

有权访问授权规则的名称及其某个签名密钥的任何客户端都可以生成 SAS 令牌。Any client that has access to name of an authorization rule name and one of its signing keys can generate a SAS token. 令牌是通过采用以下格式编写一个字符串而生成的:The token is generated by crafting a string in the following format:

SharedAccessSignature sig=<signature-string>&se=<expiry>&skn=<keyName>&sr=<URL-encoded-resourceURI>
  • se - 令牌即时过期时间。se - Token expiry instant. 一个整数,反映自 1970 年 1 月 1 日令牌过期的时期 00:00:00 UTC(UNIX 时期)以来的秒数。Integer reflecting seconds since the epoch 00:00:00 UTC on 1 January 1970 (UNIX epoch) when the token expires.

  • skn - 授权规则的名称。skn - Name of the authorization rule.

  • sr - 要访问的资源的 URL 编码 URI。sr - URL-encoded URI of the resource being accessed.

  • sig - URL 编码的 HMACSHA256 签名。sig - URL-encoded HMACSHA256 signature. 哈希计算类似于以下伪代码,并返回原始二进制输出的 base64。The hash computation looks similar to the following pseudo code and returns base64 of raw binary output.

    urlencode(base64(hmacsha256(urlencode('https://<yournamespace>.servicebus.chinacloudapi.cn/') + "\n" + '<expiry instant>', '<signing key>')))

下面是用于生成 SAS 令牌的示例 C# 代码:Here's an example C# code for generating a SAS token:

private static string createToken(string resourceUri, string keyName, string key)
    TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
    var week = 60 * 60 * 24 * 7;
    var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + week);
    string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
    HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
    var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
    return sasToken;


有关使用不同编程语言生成 SAS 令牌的示例,请参阅生成 SAS 令牌For examples of generating a SAS token using different programming languages, see Generate SAS token.

令牌包含非哈希值,使接收方可以使用相同的参数重新计算哈希,并验证颁发者是否拥有有效的签名密钥。The token contains the non-hashed values so that the recipient can recompute the hash with the same parameters, verifying that the issuer is in possession of a valid signing key.

资源 URI 是向其声明访问权限的服务总线资源的完整 URI。The resource URI is the full URI of the Service Bus resource to which access is claimed. 例如,http://<namespace>.servicebus.chinacloudapi.cn/<entityPath>sb://<namespace>.servicebus.chinacloudapi.cn/<entityPath>;即,http://contoso.servicebus.chinacloudapi.cn/contosoTopics/T1/Subscriptions/S3For example, http://<namespace>.servicebus.chinacloudapi.cn/<entityPath> or sb://<namespace>.servicebus.chinacloudapi.cn/<entityPath>; that is, http://contoso.servicebus.chinacloudapi.cn/contosoTopics/T1/Subscriptions/S3.

URI 必须采用百分比编码格式The URI must be percent-encoded.

用于签名的共享访问授权规则必须在此 URI 指定的实体上,或由其分层父级之一进行配置。The shared access authorization rule used for signing must be configured on the entity specified by this URI, or by one of its hierarchical parents. 例如,之前示例中的 http://contoso.servicebus.chinacloudapi.cn/contosoTopics/T1http://contoso.servicebus.chinacloudapi.cnFor example, http://contoso.servicebus.chinacloudapi.cn/contosoTopics/T1 or http://contoso.servicebus.chinacloudapi.cn in the previous example.

SAS 令牌对于以 signature-string 中使用的 <resourceURI> 为前缀的所有资源有效。A SAS token is valid for all resources prefixed with the <resourceURI> used in the signature-string.

重新生成密钥Regenerating keys

建议定期重新生成 SharedAccessAuthorizationRule 对象中使用的密钥。It is recommended that you periodically regenerate the keys used in the SharedAccessAuthorizationRule object. 提供了主要和辅助密钥槽,以便可以逐步轮换密钥。The primary and secondary key slots exist so that you can rotate keys gradually. 如果应用程序通常使用主要密钥,则可将主要密钥复制到辅助密钥槽,并只在完成此过程后才重新生成主要密钥。If your application generally uses the primary key, you can copy the primary key into the secondary key slot, and only then regenerate the primary key. 然后,可以在客户端应用程序(可以使用辅助槽中的旧主要密钥继续访问)中配置新的主要密钥值。The new primary key value can then be configured into the client applications, which have continued access using the old primary key in the secondary slot. 更新所有客户端后,可以重新生成辅助密钥,以便最终停用旧主要密钥。Once all clients are updated, you can regenerate the secondary key to finally retire the old primary key.

如果你知道或者怀疑密钥已泄漏,因此必须吊销这些密钥,则可以同时生成 SharedAccessAuthorizationRulePrimaryKeySecondaryKey,并用新的密钥替换它们。If you know or suspect that a key is compromised and you have to revoke the keys, you can regenerate both the PrimaryKey and the SecondaryKey of a SharedAccessAuthorizationRule, replacing them with new keys. 此过程将使得由旧密钥签名的所有令牌失效。This procedure invalidates all tokens signed with the old keys.

服务总线的共享访问签名身份验证Shared Access Signature authentication with Service Bus

下面所述的方案包括配置授权规则、生成 SAS 令牌和客户端授权。The scenarios described as follows include configuration of authorization rules, generation of SAS tokens, and client authorization.

有关演示配置和使用 SAS 授权的服务总线应用程序的完整工作示例,请参阅 Shared Access Signature authentication with Service Bus(服务总线的共享访问签名身份验证)。For a full working sample of a Service Bus application that illustrates the configuration and uses SAS authorization, see Shared Access Signature authentication with Service Bus. 演示如何使用为保护服务总线订阅,在命名空间或主题上配置的 SAS 授权规则的相关示例位于此处:Using Shared Access Signature (SAS) authentication with Service Bus Subscriptions(将共享访问签名 (SAS) 身份验证与服务总线订阅配合使用)。A related sample that illustrates the use of SAS authorization rules configured on namespaces or topics to secure Service Bus subscriptions is available here: Using Shared Access Signature (SAS) authentication with Service Bus Subscriptions.

访问实体上的共享访问授权规则Access Shared Access Authorization rules on an entity

使用服务总线 .NET Framework 库,可通过相应 QueueDescriptionTopicDescription 中的 AuthorizationRules 集合,访问在服务总线队列或主题上配置的 Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule 对象。With Service Bus .NET Framework libraries, you can access a Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule object configured on a Service Bus queue or topic through the AuthorizationRules collection in the corresponding QueueDescription or TopicDescription.

下面的代码演示了如何向队列添加授权规则。The following code shows how to add authorization rules for a queue.

// Create an instance of NamespaceManager for the operation
NamespaceManager nsm = NamespaceManager.CreateFromConnectionString(
    <connectionString> );
QueueDescription qd = new QueueDescription( <qPath> );

// Create a rule with send rights with keyName as "contosoQSendKey"
// and add it to the queue description.
qd.Authorization.Add(new SharedAccessAuthorizationRule("contosoSendKey",
    new[] { AccessRights.Send }));

// Create a rule with listen rights with keyName as "contosoQListenKey"
// and add it to the queue description.
qd.Authorization.Add(new SharedAccessAuthorizationRule("contosoQListenKey",
    new[] { AccessRights.Listen }));

// Create a rule with manage rights with keyName as "contosoQManageKey"
// and add it to the queue description.
// A rule with manage rights must also have send and receive rights.
qd.Authorization.Add(new SharedAccessAuthorizationRule("contosoQManageKey",
    new[] {AccessRights.Manage, AccessRights.Listen, AccessRights.Send }));

// Create the queue.

使用共享访问签名授权Use Shared Access Signature authorization

使用具有服务总线 .NET 库的 Azure.NET SDK 的应用程序可以通过 SharedAccessSignatureTokenProvider 类使用 SAS 授权。Applications using the Azure .NET SDK with the Service Bus .NET libraries can use SAS authorization through the SharedAccessSignatureTokenProvider class. 下面的代码演示了如何使用令牌提供程序向服务总线队列发送消息。The following code illustrates the use of the token provider to send messages to a Service Bus queue. 如果不使用此处所示的代码,还可以向令牌提供程序工厂方法传递以前颁发的令牌。Alternative to the usage shown here, you can also pass a previously issued token to the token provider factory method.

Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb",
    <yourServiceNamespace>, string.Empty);
MessagingFactory mf = MessagingFactory.Create(runtimeUri,
    TokenProvider.CreateSharedAccessSignatureTokenProvider(keyName, key));
QueueClient sendClient = mf.CreateQueueClient(qPath);

//Sending hello message to queue.
BrokeredMessage helloMessage = new BrokeredMessage("Hello, Service Bus!");
helloMessage.MessageId = "SAS-Sample-Message";

此外,可以直接使用令牌提供程序来颁发要传递给其他客户端的令牌。You can also use the token provider directly for issuing tokens to pass to other clients.

连接字符串可以包含规则名称 (SharedAccessKeyName) 和规则密钥 (SharedAccessKey) 或以前颁发的令牌 (SharedAccessSignature)。Connection strings can include a rule name (SharedAccessKeyName) and rule key (SharedAccessKey) or a previously issued token (SharedAccessSignature). 如果传递给接受连接字符串的任何构造函数或工厂方法中包含这些参数,则系统会自动创建并填充 SAS 令牌提供程序。When those are present in the connection string passed to any constructor or factory method accepting a connection string, the SAS token provider is automatically created and populated.

请注意,要使用服务总线中继的 SAS 授权,可以使用服务总线命名空间上配置的 SAS 密钥。Note that to use SAS authorization with Service Bus relays, you can use SAS keys configured on the Service Bus namespace. 如果在命名空间上显式创建中继(NamespaceManagerRelayDescription)对象,可以只为该中继设置 SAS 规则。If you explicitly create a relay on the namespace (NamespaceManager with a RelayDescription) object, you can set the SAS rules just for that relay. 要使用服务总线订阅的 SAS 授权,可以使用服务总线命名空间或主题上配置的 SAS 密钥。To use SAS authorization with Service Bus subscriptions, you can use SAS keys configured on a Service Bus namespace or on a topic.

使用共享访问签名(在 HTTP 级别)Use the Shared Access Signature (at HTTP level)

在了解如何为服务总线中的任何实体创建共享访问签名后,便可以执行 HTTP POST 了:Now that you know how to create Shared Access Signatures for any entities in Service Bus, you are ready to perform an HTTP POST:

POST https://<yournamespace>.servicebus.chinacloudapi.cn/<yourentity>/messages
Content-Type: application/json
Authorization: SharedAccessSignature sr=https%3A%2F%2F<yournamespace>.servicebus.chinacloudapi.cn%2F<yourentity>&sig=<yoursignature from code above>&se=1438205742&skn=KeyName
ContentType: application/atom+xml;type=entry;charset=utf-8

请记住,这适用于所有情况。Remember, this works for everything. 可以为队列、主题或订阅创建 SAS。You can create SAS for a queue, topic, or subscription.

如果为发送方或客户端提供 SAS 令牌,它们不会直接获取密钥,并且他们无法逆向改编哈希来获取它。If you give a sender or client a SAS token, they don't have the key directly, and they cannot reverse the hash to obtain it. 因此,可以控制它们有权访问的项以及访问时长。As such, you have control over what they can access, and for how long. 要记住的一个重点是,如果更改策略中的主密钥,基于该密钥创建的所有共享访问签名都将失效。An important thing to remember is that if you change the primary key in the policy, any Shared Access Signatures created from it are invalidated.

使用共享访问签名(在 AMQP 级别)Use the Shared Access Signature (at AMQP level)

在前一部分中,已了解如何使用 SAS 令牌配合 HTTP POST 请求将数据发送到服务总线。In the previous section, you saw how to use the SAS token with an HTTP POST request for sending data to the Service Bus. 如你所了解,可以使用高级消息队列协议 (AMQP) 来访问服务总线。在许多方案中,都会出于性能原因而将该协议用作首选协议。As you know, you can access Service Bus using the Advanced Message Queuing Protocol (AMQP) that is the preferred protocol to use for performance reasons, in many scenarios. 文档基于 AMQP 声明的安全性版本 1.0(自 2013 年以来以有效草案版推出,现已得到 Azure 的支持)中介绍了如何配合 AMQP 使用 SAS 令牌。The SAS token usage with AMQP is described in the document AMQP Claim-Based Security Version 1.0 that is in working draft since 2013 but it's supported by Azure today.

开始将数据发送到服务总线之前,发布者必须将 AMQP 消息中的 SAS 令牌发送到正确定义的名为 $cbs 的 AMQP 节点(可以将它视为一个由服务使用的“特殊”队列,用于获取和验证所有 SAS 令牌)。Before starting to send data to Service Bus, the publisher must send the SAS token inside an AMQP message to a well-defined AMQP node named $cbs (you can see it as a "special" queue used by the service to acquire and validate all the SAS tokens). 发布者必须在 AMQP 消息中指定 ReplyTo 字段;这是服务向发布者回复令牌验证结果(发布者与服务之间的简单请求/回复模式)时所在的节点。The publisher must specify the ReplyTo field inside the AMQP message; this is the node in which the service replies to the publisher with the result of the token validation (a simple request/reply pattern between publisher and service). 根据 AMQP 1.0 规范中有关“动态创建远程节点”的论述,此回复节点是“在运行中”创建的。This reply node is created "on the fly," speaking about "dynamic creation of remote node" as described by the AMQP 1.0 specification. 在检查 SAS 令牌是否有效之后,发布者可以继续将数据发送到服务。After checking that the SAS token is valid, the publisher can go forward and start to send data to the service.

下面的步骤演示如何使用 AMQP.NET Lite 库通过 AMQP 协议发送 SAS 令牌。The following steps show how to send the SAS token with AMQP protocol using the AMQP.NET Lite library. 如果无法使用官方的服务总线 SDK(例如,在 WinRT、.NET Compact Framework、.NET Micro Framework 和 Mono 中)进行 C# 开发,则这很有用。This is useful if you can't use the official Service Bus SDK (for example on WinRT, .NET Compact Framework, .NET Micro Framework and Mono) developing in C#. 当然,此库对于帮助了解基于声明的安全性如何在 AMQP 级别工作非常有用,就如同可以了解它如何在 HTTP 级别工作一样(使用 HTTP POST 请求并在“Authorization”标头内部发送 SAS 令牌)。Of course, this library is useful to help understand how claims-based security works at the AMQP level, as you saw how it works at the HTTP level (with an HTTP POST request and the SAS token sent inside the "Authorization" header). 如果不需要此类有关 AMQP 的深入知识,可以将官方的服务总线 SDK 用于 .NET Framework 应用程序,该 SDK 会为你执行此操作。If you don't need such deep knowledge about AMQP, you can use the official Service Bus SDK with .NET Framework applications, which will do it for you.


/// <summary>
/// Send claim-based security (CBS) token
/// </summary>
/// <param name="shareAccessSignature">Shared access signature (token) to send</param>
private bool PutCbsToken(Connection connection, string sasToken)
    bool result = true;
    Session session = new Session(connection);

    string cbsClientAddress = "cbs-client-reply-to";
    var cbsSender = new SenderLink(session, "cbs-sender", "$cbs");
    var cbsReceiver = new ReceiverLink(session, cbsClientAddress, "$cbs");

    // construct the put-token message
    var request = new Message(sasToken);
    request.Properties = new Properties();
    request.Properties.MessageId = Guid.NewGuid().ToString();
    request.Properties.ReplyTo = cbsClientAddress;
    request.ApplicationProperties = new ApplicationProperties();
    request.ApplicationProperties["operation"] = "put-token";
    request.ApplicationProperties["type"] = "servicebus.chinacloudapi.cn:sastoken";
    request.ApplicationProperties["name"] = Fx.Format("amqp://{0}/{1}", sbNamespace, entity);

    // receive the response
    var response = cbsReceiver.Receive();
    if (response == null || response.Properties == null || response.ApplicationProperties == null)
        result = false;
        int statusCode = (int)response.ApplicationProperties["status-code"];
        if (statusCode != (int)HttpStatusCode.Accepted && statusCode != (int)HttpStatusCode.OK)
            result = false;

    // the sender/receiver may be kept open for refreshing tokens

    return result;

PutCbsToken() 方法接收代表服务的 TCP 连接的 connection(AMQP .NET Lite 库提供的 AMQP Connection 类实例),以及表示要发送的 SAS 令牌的 sasToken 参数。The PutCbsToken() method receives the connection (AMQP connection class instance as provided by the AMQP .NET Lite library) that represents the TCP connection to the service and the sasToken parameter that is the SAS token to send.


请务必在 SASL 身份验证机制设置为 ANONYMOUS 的情况下创建连接(而不是在不需要发送 SAS 令牌时使用的包含用户名与密码的默认 PLAIN)。It's important that the connection is created with SASL authentication mechanism set to ANONYMOUS (and not the default PLAIN with username and password used when you don't need to send the SAS token).

接下来,发布者将创建两个 AMQP 链接来发送 SAS 令牌和接收来自服务的回复(此令牌验证结果)。Next, the publisher creates two AMQP links for sending the SAS token and receiving the reply (the token validation result) from the service.

AMQP 消息包含一组属性,比简单消息包含更多信息。The AMQP message contains a set of properties, and more information than a simple message. SAS 令牌是消息的正文(使用其构造函数)。The SAS token is the body of the message (using its constructor). “ReplyTo”属性设置为用于在接收方链接上接收验证结果的节点名称(可以根据需要更改其名称,该节点将由服务动态创建)。The "ReplyTo" property is set to the node name for receiving the validation result on the receiver link (you can change its name if you want, and it will be created dynamically by the service). 服务使用最后三个应用程序/自定义属性来指示它需要执行哪种类型的操作。The last three application/custom properties are used by the service to indicate what kind of operation it has to execute. 如 CBS 草案规范中所述,这些属性必须是 操作名称 ("put-token")、令牌类型(在本例中为 servicebus.chinacloudapi.cn:sastoken),以及要应用令牌的 受众的“名称” (整个实体)。As described by the CBS draft specification, they must be the operation name ("put-token"), the type of token (in this case, a servicebus.chinacloudapi.cn:sastoken), and the "name" of the audience to which the token applies (the entire entity).

在发送方链接上发送 SAS 令牌后,发布者必须在接收方链接上读取回复。After sending the SAS token on the sender link, the publisher must read the reply on the receiver link. 回复是一个简单的 AMQP 消息,其中包含一个名为 "status-code" 的应用程序属性,该属性可以包含与 HTTP 状态代码相同的值。The reply is a simple AMQP message with an application property named "status-code" that can contain the same values as an HTTP status code.

服务总线操作所需的权限Rights required for Service Bus operations

下表显示对服务总线资源进行各种操作所需的访问权限。The following table shows the access rights required for various operations on Service Bus resources.

操作Operation 所需声明Claim Required 声明范围Claim Scope
在命名空间上配置授权规则Configure authorization rule on a namespace 管理Manage 任何命名空间地址Any namespace address
服务注册表Service Registry
枚举私有策略Enumerate Private Policies 管理Manage 任何命名空间地址Any namespace address
开始在命名空间上侦听Begin listening on a namespace 侦听Listen 任何命名空间地址Any namespace address
将消息发送到命名空间中的侦听器Send messages to a listener at a namespace 发送Send 任何命名空间地址Any namespace address
创建队列Create a queue 管理Manage 任何命名空间地址Any namespace address
删除队列Delete a queue 管理Manage 任何有效队列地址Any valid queue address
枚举队列Enumerate queues 管理Manage /$Resources/Queues/$Resources/Queues
获取队列说明Get the queue description 管理Manage 任何有效队列地址Any valid queue address
在队列上配置授权规则Configure authorization rule for a queue 管理Manage 任何有效队列地址Any valid queue address
发送到队列Send into to the queue 发送Send 任何有效队列地址Any valid queue address
从队列接收消息Receive messages from a queue 侦听Listen 任何有效队列地址Any valid queue address
在速览-锁定模式下接收消息后放弃或完成消息Abandon or complete messages after receiving the message in peek-lock mode 侦听Listen 任何有效队列地址Any valid queue address
推迟消息以供将来检索Defer a message for later retrieval 侦听Listen 任何有效队列地址Any valid queue address
将消息放入死信队列Deadletter a message 侦听Listen 任何有效队列地址Any valid queue address
获取与消息队列会话关联的状态Get the state associated with a message queue session 侦听Listen 任何有效队列地址Any valid queue address
设置与消息队列会话关联的状态Set the state associated with a message queue session 侦听Listen 任何有效队列地址Any valid queue address
安排消息稍后发送;例如,ScheduleMessageAsync()Schedule a message for later delivery; for example, ScheduleMessageAsync() 侦听Listen 任何有效队列地址Any valid queue address
创建主题Create a topic 管理Manage 任何命名空间地址Any namespace address
删除主题Delete a topic 管理Manage 任何有效主题地址Any valid topic address
枚举主题Enumerate topics 管理Manage /$Resources/Topics/$Resources/Topics
获取主题描述Get the topic description 管理Manage 任何有效主题地址Any valid topic address
在主题上配置授权规则Configure authorization rule for a topic 管理Manage 任何有效主题地址Any valid topic address
发送到主题Send to the topic 发送Send 任何有效主题地址Any valid topic address
创建订阅Create a subscription 管理Manage 任何命名空间地址Any namespace address
删除订阅Delete subscription 管理Manage ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
枚举订阅Enumerate subscriptions 管理Manage ../myTopic/Subscriptions../myTopic/Subscriptions
获取订阅说明Get subscription description 管理Manage ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
在速览-锁定模式下接收消息后放弃或完成消息Abandon or complete messages after receiving the message in peek-lock mode 侦听Listen ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
推迟消息以供将来检索Defer a message for later retrieval 侦听Listen ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
将消息放入死信队列Deadletter a message 侦听Listen ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
获取与主题会话关联的状态Get the state associated with a topic session 侦听Listen ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
设置与主题会话关联的状态Set the state associated with a topic session 侦听Listen ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
创建规则Create a rule 管理Manage ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
删除规则Delete a rule 管理Manage ../myTopic/Subscriptions/mySubscription../myTopic/Subscriptions/mySubscription
枚举规则Enumerate rules 管理或侦听Manage or Listen ../myTopic/Subscriptions/mySubscription/Rules../myTopic/Subscriptions/mySubscription/Rules

后续步骤Next steps

若要了解有关服务总线消息传送的详细信息,请参阅以下主题。To learn more about Service Bus messaging, see the following topics.