我在Azure门户中创建了一个服务总线/通知中心。
现在我正试图使用Azure REST API与Postman基于此文档:https://msdn.microsoft.com/en-us/library/azure/dn223265.aspx
这是我的邮差配置:
它是以下url的POST方法(Create Registration)https://mysite.servicebus.windows.net/mysite-notif/registrations/?api-version=2015-01(出于隐私原因,我将该url中的mysite替换为)
在头文件中,我输入了两个条目:
内容类型application/atom + xml; type =条目;charset = utf - 8
授权端点=某人://(mysite) .servicebus.windows.net/; SharedAccessKeyName = DefaultFullSharedAccessSignature; SharedAccessKey = [mykey](此连接信息是从Azure门户复制的)
在Body中,我选择raw - XML(txt/XML)并粘贴:<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<WindowsRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">
<Tags>myTag, myOtherTag</Tags>
<ChannelUri>{ChannelUri}</ChannelUri>
</WindowsRegistrationDescription>
</content>
</entry>
(这是Windows通知服务的本地注册示例)
当我从Postman内部发送这个调用时,我得到一个401 Error:
<Error>
<Code>401</Code>
<Detail>MalformedToken: The credentials contained in the authorization header are not in the WRAP format..TrackingId:ee0d87ef-6175-46a1-9b35-6c31eed6049d_G2,TimeStamp:8/13/2015 9:58:26 AM</Detail>
</Error>
我错过了什么?是我在邮差中留下的"No Auth"的授权标签吗?应该像这里所示的那样编码授权头的值吗?通过REST api为Azure通知中心创建注册ID
谢谢。
下面是一个预请求脚本的示例,用于postman生成所需的标头:
function getAuthHeader(resourceUri, keyName, key) {
var d = new Date();
var sinceEpoch = Math.round(d.getTime() / 1000);
var expiry = (sinceEpoch + 3600);
var stringToSign = encodeURIComponent(resourceUri) + 'n' + expiry;
var hash = CryptoJS.HmacSHA256(stringToSign, key);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
var sasToken = 'SharedAccessSignature sr=' + encodeURIComponent(resourceUri) + '&sig=' + encodeURIComponent(hashInBase64) + '&se=' + expiry + '&skn=' + keyName;
return sasToken;
}
postman.setEnvironmentVariable('azure-authorization', getAuthHeader(request['url'], "mySharedAccessKeyName", "mySharedAccessKey"));
postman.setEnvironmentVariable('current-date',new Date().toUTCString());
使用方法如下:
- 将此预请求脚本添加到您的邮差请求
- 将
mySharedAccessKeyName
,mySharedAccessKey
替换为您的凭据 - 添加标题
Authorization: {{azure-authorization}}
- 添加标题
x-ms-date: {{current-date}}
您的"Authorization"报头不正确。
正如Azure通知中心REST API文档中所述,例如,对于创建注册,"授权"头必须包含"根据服务总线共享访问签名认证中指定的令牌"…
令牌格式在使用服务总线的共享访问签名身份验证的文档中指定如下:
SharedAccessSignature sig=<signature-string>&se=<expiry>&skn=<keyName>&sr=<URL-encoded-resourceURI>
-
URL-encoded-resourceURI
:您发送POST请求的url(在您的情况下为"https://mysite.servicebus.windows.net/mysite-notif/registrations/?api-version=2015-01") -
keyName
:在您的情况下,默认密钥名称"DefaultFullSharedAccessSignature" -
expiry
:过期表示为自1970年1月1日00:00:00 UTC以来的秒数。 -
signature-string
: SAS令牌的签名是使用带有授权规则的PrimaryKey属性的签名字符串的HMAC-SHA256计算的。要签名的字符串由一个资源URI和一个到期日期组成,格式如下:-
StringToSign = <resourceURI> + "n" + expiry;
-
resourceURI
应与URL-encoded-resourceURI
相同(也是URL编码) - 使用SAS密钥计算
StringToSign
的HMAC-SHA256(你在你的例子中用[mykey]代替)。然后使用signature-string
的URL编码结果。
-
在花了一个多小时试图理解为什么上面的步骤不工作后,我意识到如果您使用的是来自https://code.msdn.microsoft.com/Shared-Access-Signature-0a88adf8的代码,它有两个东西没有在代码的顶部定义。Key和KeyName。
关键是暗指我的部分,因为第一眼看到这里的另一个帖子,我认为它是相同的。它不是。
在Azure中:转到通知中心,然后单击>设置>访问策略,然后单击具有管理权限的策略。如果需要,可以添加策略。一旦你点击访问策略。它显示连接字符串,主要和次要。将主文件复制到剪贴板,然后放入记事本中。它看起来像这样…
端点=某人://mysite.servicebus.windows.net/; SharedAccessKeyName = DefaultFullSharedAccessSignature; SharedAccessKey = hc7qZ + pMG6zltjmASDFrskZO + Yv52D55KQUxUTSO0og =
SharedAccessKeyName = KeyName
SharedAccessKey = Key
是的,这看起来很明显,但你无法在AZURE门户中看到这些信息,除非你复制它。
所以为了完全清楚,在标题中,你通过组合+"n"+ Baris指出的到期来生成密钥"sig",但是然后你用密钥而不是KeyName签名…
我可能听起来像个白痴,但这个过程并不容易。
希望它能帮助别人。
Baris Akar的回答基本上是正确的,除了一个遗漏,无论出于什么原因,在相关文档中也没有提到:签名参数(即sig=中的签名字符串)必须是Base64编码的!
您必须像下面这样删除令牌字符串中的""。
authorizationString = resultA.replaceAll("",");
从"老SharedAccessSignature = https % 3 a % 2 f % 2 fmshub.servicebus.windows.net % 2的团体= PFZVab43PMsO0q9gz4 % 2 bfsuaqq % 5 ff05l4m7hkvbn8den0 % 3 d& se = 1553339810, skn = RootManageSharedAccessKey "
SharedAccessSignature sr 3 = https % % 2 f % 2 fmshub.servicebus.windows.net % 2的团体= PFZVab43PMsO0q9gz4 % 2 bfsuaqq % 5 ff05l4m7hkvbn8den0 % 3 d& se = 1553339810, skn = RootManageSharedAccessKey
好运。
请参阅Microsoft的以下文档以生成SAS令牌。此令牌可以在Postman中使用。
生成SAS令牌(NodeJs, Java等)
像Jérôme一样,我也使用了https://code.msdn.microsoft.com/Shared-Access-Signature-0a88adf8的示例来生成令牌,我也发现。net生成的令牌可以工作。我比较了. net生成的令牌和我的红宝石生成的令牌,发现URI.escape没有编码base64散列的最后一个字符(一个'='符号)。它也不编码"+"符号。在函数中添加字符串'=+'修复了这个问题:URI.escape(hmacb64, '=+')(我不知道是否还有其他字符应该在这里识别)
这也花了我相当多的时间来找出一种方法来生成SAS令牌在Go.
我创建了一个要点来展示如何生成这些令牌:https://gist.github.com/dennis-tra/14c63e6359f17cbb504e78d6740ca465
如果没有找到这个repo,我可能不会发现它:https://github.com/shanepeckham/GenerateSASTokenGo/blob/master/gosas.go
从D-rk的代码中工作,这可能在2022年过时了,这里是一个更新的版本,可以在Postman 10.5.6和Azure通知中心的api-version 2020-06中工作
邮差预请求脚本:
function createSharedAccessToken(sb_name, eh_name, saName, saKey) {
if (!sb_name || !eh_name || !saName || !saKey) {
throw "Missing required parameter";
}
var resourceUri = encodeURIComponent("https://" + sb_name + ".servicebus.windows.net/" + eh_name)
// Set expiration in seconds
var expires = (Date.now() / 1000) + 20 * 60;
expires = Math.ceil(expires);
var toSign = CryptoJS.enc.Utf8.parse(resourceUri + 'n' + expires);
var sa_key_utf8 = CryptoJS.enc.Utf8.parse(saKey);
var hmac = CryptoJS.HmacSHA256(toSign, sa_key_utf8);
var hmacBase64 = CryptoJS.enc.Base64.stringify(hmac);
var hmacUriEncoded = encodeURIComponent(hmacBase64);
// Construct autorization string
var token = "SharedAccessSignature sr=" + resourceUri + "&sig=" + hmacUriEncoded + "&se=" + expires + "&skn="+ saName;
return token;
}
var sb_name = "your-notification-hub-namespace";
var eh_name = "your-notification-hub-name";
//See Access Policies -> Connection String
var sa_name = "your-shared-access-key-name"
var sa_key = "your-shared-access-key-name"
var auth_header = createSharedAccessToken(sb_name, eh_name, sa_name,sa_key);
pm.environment.set('azure-authorization',auth_header);
pm.environment.set('current-date',new Date().toUTCString());
Dirk提供的解决方案帮助我解决了这个问题。但是要确保使用具有"Manage"声明访问权限的策略中的SharedAccessKeyName和SharedAccessKey。如果您只有Send和/或Listen声明,那么身份验证将无法工作并抛出一个错误—malformmedtoken:授权头中包含的凭据不是WRAP格式