使用共享访问签名 (SAS) 对事件中心资源访问进行身份验证Authenticate access to Event Hubs resources using shared access signatures (SAS)

使用共享访问签名 (SAS) 可以精细控制向具有共享访问签名的客户端授予的访问权限类型。Shared access signature (SAS) gives you granular control over the type of access you grant to the clients who has the shared access signature. 下面是可以在 SAS 中设置的一些控制措施:Here are some of the controls you can set in a SAS:

  • SAS 的有效时间间隔,包括开始时间和过期时间。The interval over which the SAS is valid, including the start time and expiry time.
  • SAS 授予的权限。The permissions granted by the SAS. 例如,事件中心命名空间的 SAS 可以授予侦听权限,但不能授予发送权限。For example, a SAS for an Event Hubs namespace might grant the listen permission, but not the send permission.
  • 只有可提供有效凭据的客户端才能将数据发送到事件中心。Only clients that present valid credentials can send data to an event hub.
  • 一个客户端无法模拟另一个客户端。A client can't impersonate another client.
  • 可以阻止恶意客户端向事件中心发送数据。A rogue client can be blocked from sending data to an event hub.

本文介绍如何使用 SAS 对事件中心资源访问进行身份验证。This article covers authenticating the access to Event Hubs resources using SAS. 若要了解如何使用 SAS 授权对事件中心资源的访问,请参阅此文To learn about authorizing access to Event Hubs resources using SAS, see this article.

Note

作为安全最佳做法,Microsoft 建议尽可能地使用 Azure AD 凭据,而不要使用更容易泄密的共享访问签名。Microsoft recommends that you use Azure AD credentials when possible as a security best practice, rather than using the shared access signatures, which can be more easily compromised. 尽管你可以继续使用共享访问签名 (SAS) 授予对事件中心资源的精细访问权限,但 Azure AD 提供了类似的功能,并且不需要管理 SAS 令牌,也不需要担心吊销已泄密的 SAS。While you can continue to use shared access signatures (SAS) to grant fine-grained access to your Event Hubs resources, Azure AD offers similar capabilities without the need to manage SAS tokens or worry about revoking a compromised SAS.

有关 Azure 事件中心内 Azure AD 集成的详细信息,请参阅使用 Azure AD 授权访问事件中心For more information about Azure AD integration in Azure Event Hubs, see Authorize access to Event Hubs using Azure AD.

配置 SAS 身份验证Configuring for SAS authentication

可以在事件中心命名空间或实体(事件中心实例或事件中心内的 Kafka 主题)中配置事件中心共享访问授权规则。You can configure the EventHubs shared access authorization rule on an Event Hubs namespace, or an entity (event hub instance or Kafka Topic in an event hub). 目前不支持在使用者组中配置共享访问授权规则,但你可以使用命名空间或实体中配置的规则来保护对使用者组的访问。Configuring a shared access authorization rule on a consumer group is currently not supported, but you can use rules configured on a namespace or entity to secure access to consumer group.

下图显示了如何对示例实体应用授权规则。The following image shows how the authorization rules apply on sample entities.

配置授权规则

在此示例中,示例事件中心命名空间 (ExampleNamespace) 有两个实体:eh1 和 topic1。In this example, the sample Event Hubs namespace (ExampleNamespace) has two entities: eh1 and topic1. 授权规则是同时在实体级别和命名空间级别定义的。The authorization rules are defined both at the entity level and also at the namespace level.

manageRuleNS、sendRuleNS 和 listenRuleNS 授权规则将同时应用到事件中心实例 eh1 和主题 t1。The manageRuleNS, sendRuleNS, and listenRuleNS authorization rules apply to both event hub instance eh1 and topic t1. listenRule-eh 和 sendRule-eh 授权规则仅应用到事件中心实例 eh1,sendRuleT 授权规则仅应用到主题 topic1。The listenRule-eh and sendRule-eh authorization rules apply only to event hub instance eh1 and sendRuleT authorization rule applies only to topic topic1.

使用 sendRuleNS 授权规则时,客户端应用程序可以同时向 eh1 和 topic1 发送消息。When using sendRuleNS authorization rule, client applications can send to both eh1 and topic1. 使用 sendRuleT 授权规则时,会强制要求仅对 topic1 进行粒度访问,因此,使用此规则进行访问的客户端应用程序现在无法向 eh1 发送消息,而只能向 topic1 发送消息。When sendRuleT authorization rule is used, it enforces granular access to topic1 only and hence client applications using this rule for access now cannot send to eh1, but only to topic1.

生成共享访问签名令牌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:

  • se – 令牌即时过期时间。se – Token expiry instant. 一个整数,反映令牌过期距 1970 年 1 月 1 日 00:00:00 UTC 纪元时间(UNIX 纪元)的秒数。Integer reflecting seconds since epoch 00:00:00 UTC on 1 January 1970 (UNIX epoch) when the token expires
  • skn – 授权规则的名称,即 SAS 密钥名称。skn – Name of the authorization rule, that is the SAS key name.
  • sr – 正在访问的资源的 URI。sr – URI of the resource being accessed.
  • sig – 签名。sig – Signature.

signature-string 是基于资源 URI 计算的 SHA-256 哈希(上一部分中所述的范围),以及令牌即时过期时间的字符串表示形式,以 CRLF 分隔。The signature-string is the SHA-256 hash computed over the resource URI (scope as described in the previous section) and the string representation of the token expiry instant, separated by CRLF.

哈希计算方式如以下虚拟代码所示,返回 256 位/32 字节哈希值。The hash computation looks similar to the following pseudo code and returns a 256-bit/32-byte hash value.

SHA-256('https://<yournamespace>.servicebus.chinacloudapi.cn/'+'\n'+ 1438205742)

令牌包含非哈希值,使接收方可以使用相同的参数重新计算哈希,并验证颁发者是否拥有有效的签名密钥。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://.servicebus.chinacloudapi.cn/sb://<namespace>.servicebus.chinacloudapi.cn/<entityPath>;,即 http://contoso.servicebus.chinacloudapi.cn/eventhubs/eh1For example, http://.servicebus.chinacloudapi.cn/ or sb://<namespace>.servicebus.chinacloudapi.cn/<entityPath>; that is, http://contoso.servicebus.chinacloudapi.cn/eventhubs/eh1.

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/eventhubs/eh1http://contoso.servicebus.chinacloudapi.cnFor example, http://contoso.servicebus.chinacloudapi.cn/eventhubs/eh1 or http://contoso.servicebus.chinacloudapi.cn in the previous example.

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

Note

使用共享访问策略为事件中心生成访问令牌。You generate an access token for Event Hubs using shared access policy. 有关详细信息,请参阅共享访问授权策略For more information, see Shared access authorization policy.

从策略生成签名(令牌)Generating a signature(token) from a policy

以下部分介绍如何使用共享访问签名策略生成 SAS 令牌。Following section shows generating a SAS token using shared access signature policies,

NodeJSNodeJS

function createSharedAccessToken(uri, saName, saKey) { 
    if (!uri || !saName || !saKey) { 
            throw "Missing required parameter"; 
        } 
    var encoded = encodeURIComponent(uri); 
    var now = new Date(); 
    var week = 60*60*24*7;
    var ttl = Math.round(now.getTime() / 1000) + week;
    var signature = encoded + '\n' + ttl; 
    var signatureUTF8 = utf8.encode(signature); 
    var hash = crypto.createHmac('sha256', saKey).update(signatureUTF8).digest('base64'); 
    return 'SharedAccessSignature sr=' + encoded + '&sig=' +  
        encodeURIComponent(hash) + '&se=' + ttl + '&skn=' + saName; 

JavaJAVA

private static String GetSASToken(String resourceUri, String keyName, String key)
  {
      long epoch = System.currentTimeMillis()/1000L;
      int week = 60*60*24*7;
      String expiry = Long.toString(epoch + week);

      String sasToken = null;
      try {
          String stringToSign = URLEncoder.encode(resourceUri, "UTF-8") + "\n" + expiry;
          String signature = getHMAC256(key, stringToSign);
          sasToken = "SharedAccessSignature sr=" + URLEncoder.encode(resourceUri, "UTF-8") +"&sig=" +
                  URLEncoder.encode(signature, "UTF-8") + "&se=" + expiry + "&skn=" + keyName;
      } catch (UnsupportedEncodingException e) {

          e.printStackTrace();
      }

      return sasToken;
  }


public static String getHMAC256(String key, String input) {
    Mac sha256_HMAC = null;
    String hash = null;
    try {
        sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        Encoder encoder = Base64.getEncoder();

        hash = new String(encoder.encode(sha256_HMAC.doFinal(input.getBytes("UTF-8"))));

    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
   } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    return hash;
}

PHPPHP

function generateSasToken($uri, $sasKeyName, $sasKeyValue) 
{ 
    $targetUri = strtolower(rawurlencode(strtolower($uri))); 
    $expires = time();  
    $expiresInMins = 60; 
    $week = 60*60*24*7;
    $expires = $expires + $week; 
    $toSign = $targetUri . "\n" . $expires; 
    $signature = rawurlencode(base64_encode(hash_hmac('sha256',             
     $toSign, $sasKeyValue, TRUE))); 
    
    $token = "SharedAccessSignature sr=" . $targetUri . "&sig=" . $signature . "&se=" . $expires .      "&skn=" . $sasKeyName; 
    return $token; 
}

C#C#

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 对事件中心发布者进行身份验证Authenticating Event Hubs publishers with SAS

事件发布者定义事件中心的虚拟终结点。An event publisher defines a virtual endpoint for an event hub. 发布者只可用于将消息发送到事件中心,而不可用于接收消息。The publisher can only be used to send messages to an event hub and not receive messages.

通常,事件中心为每个客户端使用一个发布者。Typically, an event hub employs one publisher per client. 发送到事件中心的任何发布者的所有消息都会在该事件中心内排队。All messages that are sent to any of the publishers of an event hub are enqueued within that event hub. 发布者可以实现精细访问控制。Publishers enable fine-grained access control.

为每个事件中心客户端分配一个唯一令牌,该令牌将上传到客户端。Each Event Hubs client is assigned a unique token, which is uploaded to the client. 生成令牌后,每个唯一令牌授予对不同唯一发布者的访问权限。The tokens are produced such that each unique token grants access to different unique publisher. 持有令牌的客户端只能向一个发布者发送消息,但不能向其他发布者发送消息。A client that holds a token can only send to one publisher, and no other publisher. 如果多个客户端共享同一令牌,则其中每个客户端都会共享该发布者。If multiple clients share the same token, then each of them shares the publisher.

为所有令牌分配 SAS 密钥。All tokens are assigned with SAS keys. 通常,所有令牌使用同一密钥进行签名。Typically, all tokens are signed with the same key. 客户端不知道密钥,这可以防止客户端制造令牌。Clients aren't aware of the key, which prevents clients from manufacturing tokens. 客户端以相同的令牌运行,直到令牌过期。Clients operate on the same tokens until they expire.

例如,若要定义范围限定为向事件中心发送/发布消息的授权规则,需要定义发送授权规则。For example, to define authorization rules scoped down to only sending/publishing to Event Hubs, you need to define a send authorization rule. 可以在命名空间级别执行此操作,或者为特定的实体(事件中心实例或主题)分配更精细的范围。This can be done at a namespace level or give more granular scope to a particular entity (event hubs instance or a topic). 具有此类粒度访问范围的客户端或应用程序称为“事件中心发布者”。A client or an application that is scoped with such granular access is called, Event Hubs publisher. 为此,请执行以下步骤:To do so, follow these steps:

  1. 在要发布的实体中创建一个 SAS 密钥,以在其上分配发送范围。Create a SAS key on the entity you want to publish to assign the send scope on it. 有关详细信息,请参阅共享访问授权策略For more information, see Shared access authorization policies.

  2. 使用在步骤 1 中生成的密钥为特定的发布者生成具有过期时间的 SAS 令牌。Generate a SAS token with an expiry time for a specific publisher by using the key generated in step1.

    var sasToken = SharedAccessSignatureTokenProvider.GetPublisherSharedAccessSignature(
                new Uri("Service-Bus-URI"),
                "eventub-name",
                "publisher-name",
                "sas-key-name",
                "sas-key",
                TimeSpan.FromMinutes(30));
    
  3. 向发布者客户端提供令牌,该客户端只能将消息发送到令牌授予了访问权限的实体和发布者。Provide the token to the publisher client, which can only send to the entity and the publisher that token grants access to.

    令牌过期后,客户端将失去向该实体发送/发布消息的访问权限。Once the token expires, the client loses its access to send/publish to the entity.

Note

可为设备配置令牌,用于授予对事件中心或命名空间的访问权限,但不建议这样做。Although it's not recommended, it is possible to equip devices with tokens that grant access to an event hub or a namespace. 持有此令牌的任何设备都可以直接将消息发送到该事件中心。Any device that holds this token can send messages directly to that event hub. 此外,无法将设备列入阻止列表,使其无法向该事件中心发送消息。Furthermore, the device cannot be blacklisted from sending to that event hub.

我们始终建议指定具体的精细范围。It's always recommended to give specific and granular scopes.

Important

创建令牌后,会为每个客户端设置其自身唯一的令牌。Once the tokens have been created, each client is provisioned with its own unique token.

当客户端向事件中心发送数据时,客户端会使用令牌标记其请求。When the client sends data into an event hub, it tags its request with the token. 为了防止攻击者窃听和盗取令牌,客户端与事件中心之间的通信必须通过加密通道进行。To prevent an attacker from eavesdropping and stealing the token, the communication between the client and the event hub must occur over an encrypted channel.

如果令牌被攻击者盗取,攻击者可能会模拟令牌已被盗的客户端。If a token is stolen by an attacker, the attacker can impersonate the client whose token has been stolen. 将发布者列入方块列表会导致客户端不可用,直至该客户端收到使用其他发布者的新令牌。Blacklisting a publisher, renders that client unusable until it receives a new token that uses a different publisher.

使用 SAS 对事件中心使用者进行身份验证Authenticating Event Hubs consumers with SAS

若要对使用事件中心生成者生成的数据的后端应用程序进行身份验证,事件中心令牌身份验证要求其客户端对其事件中心命名空间或者事件中心实例或主题拥有管理权限或侦听权限。To authenticate back-end applications that consume from the data generated by Event Hubs producers, Event Hubs token authentication requires its clients to either have the manage rights or the listen privileges assigned to its Event Hubs namespace or event hub instance or topic. 通过使用者组使用事件中心内的数据。Data is consumed from Event Hubs using consumer groups. 尽管 SAS 策略可以提供精细范围,但此范围仅仅是在实体级别定义的,而不是在使用者级别定义的。While SAS policy gives you granular scope, this scope is defined only at the entity level and not at the consumer level. 这意味着,在命名空间级别或者事件中心实例或主题级别定义的特权将应用到该实体的使用者组。It means that the privileges defined at the namespace level or the event hub instance or topic level will be applied to the consumer groups of that entity.

后续步骤Next steps

请参阅以下文章:See the following articles:

请参阅以下相关文章:See the following related articles: