Concetti comuni

 

Analizzare la stringa di connessione

Per accedere a un hub di notifica, è necessario disporre di due tipi di informazioni: il nome dell'hub (può essere un percorso, ad esempio "a/b/c") e una stringa di connessione. La stringa di connessione contiene informazioni relative all'endpoint dell'hub e le credenziali di sicurezza utilizzate per accedervi (nel caso di SAS, contiene un nome di regola e un valore di chiave).

Il seguente codice analizza la stringa di connessione per estrarre le informazioni rilevanti:

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); } } }  
  
String[] parts = connectionString.split(";"); if (parts.length != 3) throw new RuntimeException("Error parsing connection string: " + connectionString); for (int i = 0; i < parts.length; i++) { if (parts[i].startsWith("Endpoint")) { this.endpoint = "https" + parts[i].substring(11); } else if (parts[i].startsWith("SharedAccessKeyName")) { this.SasKeyName = parts[i].substring(20); } else if (parts[i].startsWith("SharedAccessKey")) { this.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); } });  

Creare SAS Token di sicurezza

Per eseguire l'autenticazione tramite SAS, un client deve specificare un token di firma di accesso condiviso nel Authorization intestazione delle richieste. Il token è costituito da informazioni estratte dalla stringa di connessione e la richiesta corrente che deve essere autenticata. Il token ha il formato seguente:

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

Si noti che il token fa riferimento a un keyName (per inviare notifiche, in genere utilizzano il DefaultFullSharedAccessSignature proprietà che viene creato automaticamente in tutti gli hub di notifica).

La firma per il token SAS viene calcolata utilizzando l'algoritmo HMAC-SHA256 di un valore stringa da firmare con la PrimaryKey proprietà di una regola di autorizzazione. Il valore di stringa da firmare è costituita da un URI di risorsa e una scadenza ed è formattato nel modo seguente:

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

Si noti che è necessario utilizzare l'URI di risorsa non codificato per questa operazione. L'URI di risorsa è l'URI completo del Bus di servizio risorse a cui si desidera accedere. Il formato è il seguente:

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

Ad esempio:

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

La scadenza è rappresentata come il numero di secondi dopo l'ora UTC 00:00:00 periodo 1 gennaio 1970.

La regola di autorizzazione di accesso condiviso utilizzata per la firma deve essere configurata nell'entità specificata dall'URI. Nell'esempio precedente, si tratta http://contoso.servicebus.windows.net/myHub o http://contoso.servicebus.windows.net.

Con codifica URL resourceURI deve corrispondere all'URI utilizzato nella stringa da firmare durante il calcolo della firma. Dovrebbe essere codificati in percentuale e lettere minuscole.

Il seguente codice, dato un URI della richiesta, crea un token SAS. La versione Java utilizza Apache Commons Codec e la versione Javascript utilizza 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; } }  
  
private String generateSasToken(URI uri) { String targetUri; try { targetUri = URLEncoder .encode(uri.toString().toLowerCase(), "UTF-8") .toLowerCase(); long expiresOnDate = System.currentTimeMillis(); int expiresInMins = 60; // 1 hour expiresOnDate += expiresInMins * 60 * 1000; long expires = expiresOnDate / 1000; String toSign = targetUri + "\n" + expires; // Get an hmac_sha1 key from the raw key bytes byte[] keyBytes = SasKeyValue.getBytes("UTF-8"); SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256"); // Get an hmac_sha1 Mac instance and initialize with the signing key Mac mac = Mac.getInstance("HmacSHA256"); mac.init(signingKey); // Compute the hmac on input data bytes byte[] rawHmac = mac.doFinal(toSign.getBytes("UTF-8")); // using Apache commons codec for base64 String signature = URLEncoder.encode( Base64.encodeBase64String(rawHmac), "UTF-8"); // construct authorization string String token = "SharedAccessSignature sr=" + targetUri + "&sig=" + signature + "&se=" + expires + "&skn=" + SasKeyName; return token; } catch (Exception e) { throw new RuntimeException(e); } }  
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; };