常見概念
本文提供開發使用 Azure 通知中樞 REST API 的應用程式時的常見概念。
注意
為了確保安全性層級較高,通知中樞會在 2020 年 4 月 30 日停用 TLS 1.0 和 1.1 版的支援。 如需詳細資訊,請參閱 Azure 通知中樞檔中的 傳輸層安全性 (TLS) 。
剖析連接字串
若要存取通知中樞,您必須有兩項資訊:中樞名稱和連接字串。 連接字串包含中樞端點的相關資訊,以及用來存取它的安全性認證 (For 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 進行驗證,用戶端必須在其要求的授權標頭中指定 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
有效期限會以從新紀元時間 (Epoch) 1970 年 1 月 1日 00:00:00 UTC 時間至今的秒數表示。
用於簽署的共用存取授權規則必須在此 URI 所指定的實體上設定。 在上一個範例中,URI 是 http://contoso.servicebus.windows.net/myHub
或 http://contoso.servicebus.windows.net
。
URL 編碼 的 resourceURI 必須與簽章計算期間在字串對簽署中使用的 URI 相同。 它應該是百分比編碼和小寫。
下列程式碼指定要求 URI,會建立 SAS 權杖。 JAVA 版本使用 Apache Commons Codec,而 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;
};