Běžné koncepty
Tento článek obsahuje běžné koncepty při vývoji aplikací, které používají rozhraní REST API služby Azure Notification Hubs.
Poznámka
Aby byla zajištěna vyšší úroveň zabezpečení, služba Notification Hubs 30. dubna 2020 zakáže podporu protokolu TLS verze 1.0 a 1.1. Další informace najdete v tématu Tls (Transport Layer Security) v dokumentaci ke službě Azure Notification Hubs.
Analýza připojovacího řetězce
Pokud chcete získat přístup k centru oznámení, musíte mít dvě informace: název centra a připojovací řetězec. Připojovací řetězec obsahuje informace o koncovém bodu vašeho centra a přihlašovacích údaji zabezpečení, které se k němu používají (v případě SAS obsahuje název pravidla a hodnotu klíče).
Následující kód analyzuje připojovací řetězec a extrahuje relevantní informace:
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);
}
});
Vytvoření tokenu zabezpečení SAS
Aby bylo možné ověřování pomocí SAS, musí klient zadat token SAS v autorizační hlavičce svých požadavků. Token je vytvořen na základě informací extrahovaných z připojovacího řetězce a aktuálního požadavku, který se musí ověřit. Token má následující tvar:
SharedAccessSignature sig=<signature-string>&se=<expiry>&skn=<keyName>&sr=<URL-encoded-resourceURI>
Token odkazuje na keyName (k odesílání oznámení obvykle používáte vlastnost DefaultFullSharedAccessSignature , která se automaticky vytvoří ve všech centrech oznámení).
Podpis tokenu SAS se vypočítá pomocí HMAC-SHA256 hodnoty string-to-sign s vlastností PrimaryKey autorizačního pravidla. Hodnota string-to-sign se skládá z identifikátoru URI prostředku a vypršení platnosti, které jsou naformátované takto:
StringToSign = <resourceURI> + "\n" + expiry;
Pro tuto operaci použijte identifikátor URI nezakódovaného prostředku. Identifikátor URI prostředku je úplný identifikátor URI prostředku služby Service Bus, ke kterému se nárokuje přístup. Formulář je následující:
http://<namespace>.servicebus.windows.net/<hubName>
Příklad:
http://contoso.servicebus.windows.net/myHub
Vypršení platnosti je vyjádřeno jako počet sekund od epochy 00:00:00 UTC dne 1. ledna 1970.
Autorizační pravidlo sdíleného přístupu použité k podepisování musí být nakonfigurované pro entitu určenou tímto identifikátorem URI. V předchozím příkladu je http://contoso.servicebus.windows.net/myHub
identifikátor URI nebo http://contoso.servicebus.windows.net
.
Identifikátor resourceURI kódovaný adresou URL musí být stejný jako identifikátor URI použitý v řetězci k sign během výpočtu podpisu. Měla by být zakódovaná jako procenta a malá písmena.
Následující kód s identifikátorem URI požadavku vytvoří token SAS. Verze Java používá kodek Apache Commons a verze JavaScriptu používá 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;
};