如何通过Javascript(node.js)生成Azure SAS令牌 [英] How to generate an Azure SAS token via Javascript (node.js)
问题描述
我试图生成一个有效的SAS令牌(共享访问签名)以连接到Azure IoT中心,但是在使用令牌时,我不断收到错误消息拒绝连接:未经授权
.
我知道我的连接方式有效,因为使用Microsoft设备资源管理器( https://docs.microsoft.com/zh-cn/azure/storage/common/storage-dotnet-shared-access-signature-part-1 与一些正常工作进行比较实现:
在以下Javascript实现中我在做错什么?我认为这可能与SHA256签名和URL转义字符串相关,但我不确定如何测试/验证./p>
const crypto = require('crypto');//在Azure门户上://sharedAccessKeyName是策略"字段//sharedAccessKeyValue是主键"常量符号=(iotHubName,expirtyDeltaInSecondsFromNow,sharedAccessKeyName,sharedAccessKeyValue)=>{//URL编码IoT Hub主机const encodeSasUrl = encodeURI(`$ {iotHubName} .azure-devices.net`.toLowerCase());//将过期结束日期时间计算为一个纪元const expiry = parseInt(Date.now()/1000 + expirtyDeltaInSecondsFromNow);//合并前两个信息const stringToSign =`$ {encodedSasUrl} \ n $ {expiry}`;//使用主键(sharedAccessKeyValue)和SHA256对字符串进行签名const hmac = crypto.createHmac('sha256',sharedAccessKeyValue);hmac.update(stringToSign);const hash = hmac.digest('hex');//将签名的哈希编码为base64(确保其网址已转义)const encodeSignature = hash.toString('base64');//将所有内容放到SAS令牌中const sasToken =`SharedAccessSignature sig = $ {encodedSignature}& se = $ {expiry}& skn = $ {sharedAccessKeyName}& sr = $ {encodedSasUrl}`;console.log("sasToken:",sasToken);返回sasToken;}
此处是通过node.js生成SAS令牌的示例.
var generateSasToken = function(resourceUri,signingKey,policyName,expiresInMins){resourceUri = encodeURIComponent(resourceUri);//设置过期时间(以秒为单位)var expires =(Date.now()/1000)+ expiresInMins * 60;过期= Math.ceil(过期);var toSign = resourceUri +'\ n'+到期;//使用加密var hmac = crypto.createHmac('sha256',new Buffer(signingKey,'base64'));hmac.update(toSign);var base64UriEncoded = encodeURIComponent(hmac.digest('base64'));//构造自定义字符串var token ="SharedAccessSignature sr =" + resourceUri +& sig ="+ base64UriEncoded +& se =" +到期;如果(policyName)令牌+ =& skn =" + policyName;返回令牌;};
在以下Javascript实现中我怎么了?
我不是javascript(node.js)的专家.也许您可以通过比较上面的代码和您的代码来弄清楚.
I am trying to generate a valid SAS token (shared access signatures) to connect to the Azure IoT Hub, but I keep getting the error Connection refused: Not authorized
when using the token.
I know the way I am connecting is working because when using a SAS token generated with the Microsoft Device Explorer (https://github.com/Azure/azure-iot-sdk-csharp/tree/master/tools/DeviceExplorer) it works as expected.
To write the Javascript code I started from this documentation https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1 comparing with some working implementations:
- in Python: https://github.com/Azure/azure-sdk-for-python/blob/master/azure-servicebus/azure/servicebus/servicebusservice.py
- in Go/Golang: https://github.com/openenergi/go-event-hub/blob/master/msauth/sasl.go
What am I doing wrong in the following Javascript implementation? I think it may be related to the SHA256 signature combined with URL escaping the string but I am not sure how to test/verify this.
const crypto = require('crypto');
// on the Azure Portal:
// sharedAccessKeyName is the "policy" field
// sharedAccessKeyValue is the "primary key"
const sign = (iotHubName, expirtyDeltaInSecondsFromNow, sharedAccessKeyName, sharedAccessKeyValue) => {
// URL encode the IoT Hub host
const encodedSasUrl = encodeURI(`${iotHubName}.azure-devices.net`.toLowerCase());
// calculate the expiry end datetime as an epoch
const expiry = parseInt(Date.now() / 1000 + expirtyDeltaInSecondsFromNow);
// combine the previous two pieces of information
const stringToSign = `${encodedSasUrl}\n${expiry}`;
// sign the string using the primary key (sharedAccessKeyValue) and SHA256
const hmac = crypto.createHmac('sha256', sharedAccessKeyValue);
hmac.update(stringToSign);
const hash = hmac.digest('hex');
// encode the signed hash to base64 (making sure it's URL escaped)
const encodedSignature = hash.toString('base64');
// put all together into the SAS token
const sasToken = `SharedAccessSignature sig=${encodedSignature}&se=${expiry}&skn=${sharedAccessKeyName}&sr=${encodedSasUrl}`;
console.log("sasToken:", sasToken);
return sasToken;
}
Here is an example of generating SAS token via node.js.
var generateSasToken = function(resourceUri, signingKey, policyName, expiresInMins) {
resourceUri = encodeURIComponent(resourceUri);
// Set expiration in seconds
var expires = (Date.now() / 1000) + expiresInMins * 60;
expires = Math.ceil(expires);
var toSign = resourceUri + '\n' + expires;
// Use crypto
var hmac = crypto.createHmac('sha256', new Buffer(signingKey, 'base64'));
hmac.update(toSign);
var base64UriEncoded = encodeURIComponent(hmac.digest('base64'));
// Construct autorization string
var token = "SharedAccessSignature sr=" + resourceUri + "&sig="
+ base64UriEncoded + "&se=" + expires;
if (policyName) token += "&skn="+policyName;
return token;
};
What am I doing wrong in the following Javascript implementation?
I am not an expert on javascript(node.js). Maybe you can figure it out via comparing above code and yours.
这篇关于如何通过Javascript(node.js)生成Azure SAS令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!