从 Dynamics NAV 生成 Azure 服务总线 SAS 令牌
Generate Azure Service Bus SAS Token from Dynamics NAV
我正在尝试使用 DotNet 从 Dynamics NAV 2018 生成 SAS 令牌。
我在 PowerShell 中有一个工作代码,我一直在使用它进行测试:
$epoch = Get-Date -Date "1970-01-01 00:00:00Z"
$epoch.ToUniversalTime() | Out-Null
$utcNow = Get-Date
$utcNow.ToUniversalTime() | Out-Null
$sinceEpoch = New-TimeSpan -Start $epoch -End $utcNow
$expiry = [System.Convert]::ToString([int32]$sinceEpoch.TotalSeconds + 3600)
$stringToSign = [System.Web.HttpUtility]::UrlEncode($resourceUri) + "`n" + $expiry
$hamcsha = New-Object System.Security.Cryptography.HMACSHA256
$hamcsha.Key = [Text.Encoding]::UTF8.GetBytes($key);
$signature = [System.Convert]::ToBase64String($hamcsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign)))
$token = [System.String]::Format([System.Globalization.CultureInfo]::InvariantCulture,"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",[System.Web.HttpUtility]::UrlEncode($resourceUri),[System.Web.HttpUtility]::UrlEncode($signature),$expiry,$keyName);
这是 C/AL 代码,但我得到 (401) Unauthorized 并且令牌看起来有点不同
Epoch := CREATEDATETIME(DMY2DATE(1,1,1970),000000T);
SinceEpoch := ( CURRENTDATETIME - Epoch ) / 1000;
Expiry := Convert.ToString(ROUND((SinceEpoch + 3600),1,'<'));
StringToSign := HttpUtility.UrlEncode(AzureServiceBusQueue.URL) + Environment.NewLine + Expiry;
HMACSHA256 := HMACSHA256.HMACSHA256(Encoding.UTF8.GetBytes(AzureServiceBusQueue.Key));
Signature := Convert.ToBase64String(HMACSHA256.ComputeHash(Encoding.UTF8.GetBytes(StringToSign)));
Token := Convert.ToString(STRSUBSTNO('SharedAccessSignature sr=%1&sig=%2&se=%3&skn=%4',
HttpUtility.UrlEncode(AzureServiceBusQueue.URL),
HttpUtility.UrlEncode(Signature),
Expiry,
AzureServiceBusQueue."Key Name"),
CultureInfo.InvariantCulture);
DotNet 变量是:
AzureServiceBusQueue@1000000001 : Record 54000;
HttpUtility@1000000005 : DotNet "'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Web.HttpUtility";
HMACSHA256@1000000007 : DotNet "'mscorlib'.System.Security.Cryptography.HMACSHA256";
Convert@1000000008 : DotNet "'mscorlib'.System.Convert";
Encoding@1000000009 : DotNet "'mscorlib'.System.Text.Encoding";
CultureInfo@1000000012 : DotNet "'mscorlib'.System.Globalization.CultureInfo";
Environment@1000000014 : DotNet "'mscorlib'.System.Environment";
如果我尝试使用 PowerShell 脚本中的 C/AL 代码生成的令牌,我会得到相同的结果:(401) Unauthorized
有什么想法吗?
让我回答我自己的问题...问题出在 Environment.NewLine 因为它是 CRLF 但 \n 只是 LF。因此我已经替换了它,这是正确的代码(NewLine 是 Text[1]):
Epoch := CREATEDATETIME(DMY2DATE(1,1,1970),000000T);
SinceEpoch := ( CURRENTDATETIME - Epoch ) / 1000;
Expiry := Convert.ToString(ROUND((SinceEpoch + 3600),1,'<'));
NewLine = 10;
StringToSign := HttpUtility.UrlEncode(AzureServiceBusQueue.URL) + NewLine + Expiry;
HMACSHA256 := HMACSHA256.HMACSHA256(Encoding.UTF8.GetBytes(AzureServiceBusQueue.Key));
Signature := Convert.ToBase64String(HMACSHA256.ComputeHash(Encoding.UTF8.GetBytes(StringToSign)));
Token := Convert.ToString(STRSUBSTNO('SharedAccessSignature sr=%1&sig=%2&se=%3&skn=%4',
HttpUtility.UrlEncode(AzureServiceBusQueue.URL),
HttpUtility.UrlEncode(Signature),
Expiry,
AzureServiceBusQueue."Key Name"),
CultureInfo.InvariantCulture);
我正在尝试使用 DotNet 从 Dynamics NAV 2018 生成 SAS 令牌。 我在 PowerShell 中有一个工作代码,我一直在使用它进行测试:
$epoch = Get-Date -Date "1970-01-01 00:00:00Z"
$epoch.ToUniversalTime() | Out-Null
$utcNow = Get-Date
$utcNow.ToUniversalTime() | Out-Null
$sinceEpoch = New-TimeSpan -Start $epoch -End $utcNow
$expiry = [System.Convert]::ToString([int32]$sinceEpoch.TotalSeconds + 3600)
$stringToSign = [System.Web.HttpUtility]::UrlEncode($resourceUri) + "`n" + $expiry
$hamcsha = New-Object System.Security.Cryptography.HMACSHA256
$hamcsha.Key = [Text.Encoding]::UTF8.GetBytes($key);
$signature = [System.Convert]::ToBase64String($hamcsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign)))
$token = [System.String]::Format([System.Globalization.CultureInfo]::InvariantCulture,"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",[System.Web.HttpUtility]::UrlEncode($resourceUri),[System.Web.HttpUtility]::UrlEncode($signature),$expiry,$keyName);
这是 C/AL 代码,但我得到 (401) Unauthorized 并且令牌看起来有点不同
Epoch := CREATEDATETIME(DMY2DATE(1,1,1970),000000T);
SinceEpoch := ( CURRENTDATETIME - Epoch ) / 1000;
Expiry := Convert.ToString(ROUND((SinceEpoch + 3600),1,'<'));
StringToSign := HttpUtility.UrlEncode(AzureServiceBusQueue.URL) + Environment.NewLine + Expiry;
HMACSHA256 := HMACSHA256.HMACSHA256(Encoding.UTF8.GetBytes(AzureServiceBusQueue.Key));
Signature := Convert.ToBase64String(HMACSHA256.ComputeHash(Encoding.UTF8.GetBytes(StringToSign)));
Token := Convert.ToString(STRSUBSTNO('SharedAccessSignature sr=%1&sig=%2&se=%3&skn=%4',
HttpUtility.UrlEncode(AzureServiceBusQueue.URL),
HttpUtility.UrlEncode(Signature),
Expiry,
AzureServiceBusQueue."Key Name"),
CultureInfo.InvariantCulture);
DotNet 变量是:
AzureServiceBusQueue@1000000001 : Record 54000;
HttpUtility@1000000005 : DotNet "'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Web.HttpUtility";
HMACSHA256@1000000007 : DotNet "'mscorlib'.System.Security.Cryptography.HMACSHA256";
Convert@1000000008 : DotNet "'mscorlib'.System.Convert";
Encoding@1000000009 : DotNet "'mscorlib'.System.Text.Encoding";
CultureInfo@1000000012 : DotNet "'mscorlib'.System.Globalization.CultureInfo";
Environment@1000000014 : DotNet "'mscorlib'.System.Environment";
如果我尝试使用 PowerShell 脚本中的 C/AL 代码生成的令牌,我会得到相同的结果:(401) Unauthorized
有什么想法吗?
让我回答我自己的问题...问题出在 Environment.NewLine 因为它是 CRLF 但 \n 只是 LF。因此我已经替换了它,这是正确的代码(NewLine 是 Text[1]):
Epoch := CREATEDATETIME(DMY2DATE(1,1,1970),000000T);
SinceEpoch := ( CURRENTDATETIME - Epoch ) / 1000;
Expiry := Convert.ToString(ROUND((SinceEpoch + 3600),1,'<'));
NewLine = 10;
StringToSign := HttpUtility.UrlEncode(AzureServiceBusQueue.URL) + NewLine + Expiry;
HMACSHA256 := HMACSHA256.HMACSHA256(Encoding.UTF8.GetBytes(AzureServiceBusQueue.Key));
Signature := Convert.ToBase64String(HMACSHA256.ComputeHash(Encoding.UTF8.GetBytes(StringToSign)));
Token := Convert.ToString(STRSUBSTNO('SharedAccessSignature sr=%1&sig=%2&se=%3&skn=%4',
HttpUtility.UrlEncode(AzureServiceBusQueue.URL),
HttpUtility.UrlEncode(Signature),
Expiry,
AzureServiceBusQueue."Key Name"),
CultureInfo.InvariantCulture);