你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

常见概念

本文提供开发使用 Azure 通知中心 REST API 的应用程序时的常见概念。

注意

为确保更高级别的安全性,通知中心将于 2020 年 4 月 30 日禁用对 TLS 版本 1.0 和 1.1 的支持。 有关详细信息,请参阅 Azure 通知中心文档中 的传输层安全性 (TLS)

分析连接字符串

若要访问通知中心,必须有两条信息:中心名称和连接字符串。 连接字符串包含有关中心终结点的信息,以及用于访问中心的安全凭据 (对于 SAS,它包含规则名称和密钥值) 。

以下代码分析连接字符串以提取相关信息:

public partial class ConnectionStringUtility
{
    public string Endpoint { get; private set; }
    public string SasKeyName { get; private set; }
    public string SasKeyValue { get; private set; }

    public ConnectionStringUtility(string connectionString)
    {
        //Parse Connectionstring
        char[] separator = { ';' };
        string[] parts = connectionString.Split(separator);
        for (int i = 0; i < parts.Length; i++)
        {
            if (parts[i].StartsWith("Endpoint"))
                Endpoint = "https" + parts[i].Substring(11);
            if (parts[i].StartsWith("SharedAccessKeyName"))
                SasKeyName = parts[i].Substring(20);
            if (parts[i].StartsWith("SharedAccessKey"))
                SasKeyValue = parts[i].Substring(16);
        }
    }
}
var parts = connectionString.split(';');
if (parts.length != 3)
throw "Error parsing connection string";

parts.forEach(function(part) {
if (part.indexOf('Endpoint') == 0) {
endpoint = 'https' + part.substring(11);
} else if (part.indexOf('SharedAccessKeyName') == 0) {
sasKeyName = part.substring(20);
} else if (part.indexOf('SharedAccessKey') == 0) {
sasKeyValue = part.substring(16);
}
});

创建 SAS 安全令牌

若要使用 SAS 进行身份验证,客户端必须在其请求的 Authorization 标头中指定 SAS 令牌。 令牌是从连接字符串中提取的信息和必须进行身份验证的当前请求构造的。 令牌具有以下形式:

SharedAccessSignature sig=<signature-string>&se=<expiry>&skn=<keyName>&sr=<URL-encoded-resourceURI>

令牌引用用于发送通知的 keyName (,通常使用在所有通知中心) 自动创建的 DefaultFullSharedAccessSignature 属性。

SAS 令牌的签名是使用字符串到签名值的 HMAC-SHA256 和授权规则的 PrimaryKey 属性计算的。 字符串到签名值由资源 URI 和过期组成,格式如下:

StringToSign = <resourceURI> + "\n" + expiry;

对此操作使用未编码的资源 URI。 资源 URI 是向其声明访问权限的服务总线资源的完整 URI。 窗体如下所示:

http://<namespace>.servicebus.windows.net/<hubName>

例如:

http://contoso.servicebus.windows.net/myHub

到期时间表示为自 1970 年 1 月 1 日 00:00:00 UTC 时期以后的秒数。

必须在此 URI 指定的实体上配置用于签名的共享访问授权规则。 在上一示例中,URI 为 http://contoso.servicebus.windows.net/myHubhttp://contoso.servicebus.windows.net

URL 编码 的 resourceURI 必须与计算签名期间字符串到签名中使用的 URI 相同。 它应采用百分比编码和小写形式。

在给定请求 URI 的情况下,以下代码将创建 SAS 令牌。 Java 版本使用 Apache Commons 编解码器,Javascript 版本使用 CryptoJS。

public partial class ConnectionStringUtility
{
    public string getSaSToken(string uri, int minUntilExpire)
    {
        string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();

        // Add an expiration in seconds to it.
        long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
        expiresOnDate += minUntilExpire * 60 * 1000;
        long expires_seconds = expiresOnDate / 1000;
        String toSign = targetUri + "\n" + expires_seconds;

        // Generate a HMAC-SHA256 hash or the uri and expiration using your secret key.
        MacAlgorithmProvider macAlgorithmProvider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
        BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;
        var messageBuffer = CryptographicBuffer.ConvertStringToBinary(toSign, encoding);
        IBuffer keyBuffer = CryptographicBuffer.ConvertStringToBinary(SasKeyValue, encoding);
        CryptographicKey hmacKey = macAlgorithmProvider.CreateKey(keyBuffer);
        IBuffer signedMessage = CryptographicEngine.Sign(hmacKey, messageBuffer);

        string signature = Uri.EscapeDataString(CryptographicBuffer.EncodeToBase64String(signedMessage));

        return "SharedAccessSignature sr=" + targetUri + "&sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName;
    }
}
var getSelfSignedToken = function(targetUri, sharedKey, ruleId,
expiresInMins) {
targetUri = encodeURIComponent(targetUri.toLowerCase()).toLowerCase();

// Set expiration in seconds
var expireOnDate = new Date();
expireOnDate.setMinutes(expireOnDate.getMinutes() + expiresInMins);
var expires = Date.UTC(expireOnDate.getUTCFullYear(), expireOnDate
.getUTCMonth(), expireOnDate.getUTCDate(), expireOnDate
.getUTCHours(), expireOnDate.getUTCMinutes(), expireOnDate
.getUTCSeconds()) / 1000;
var tosign = targetUri + '\n' + expires;

// using CryptoJS
var signature = CryptoJS.HmacSHA256(tosign, sharedKey);
var base64signature = signature.toString(CryptoJS.enc.Base64);
var base64UriEncoded = encodeURIComponent(base64signature);

// construct autorization string
var token = "SharedAccessSignature sr=" + targetUri + "&sig="
+ base64UriEncoded + "&se=" + expires + "&skn=" + ruleId;
// console.log("signature:" + token);
return token;
};