我正尝试通过REST API在R中使用Azure存储。我正在使用httr
包,它覆盖了Curl。
设置
您可以使用R-fiddle:http://www.r-fiddle.org/#/fiddle?id=vh8uqGmM
library(httr)
requestdate<-format(Sys.time(),"%a, %d %b %Y %H:%M:%S GMT")
url<-"https://preconstuff.blob.core.windows.net/pings?restype=container&comp=list"
sak<-"Q8HvUVJLBJK+wkrIEG6LlsfFo19iDjneTwJxX/KXSnUCtTjgyyhYnH/5azeqa1bluGD94EcPcSRyBy2W2A/fHQ=="
signaturestring<-paste0("GET",paste(rep("\n",12),collapse=""),
"x-ms-date:",requestdate,"
x-ms-version:2009-09-19
/preconstuff/pings
comp:list
restype:container")
headerstuff<-add_headers(Authorization=paste0("SharedKey preconstuff:",
RCurl::base64(digest::hmac(key=sak,
object=enc2utf8(signaturestring),
algo= "sha256"))),
`x-ms-date`=requestdate,
`x-ms-version`= "2009-09-19")
尝试列出 blobs:
content(GET(url,config = headerstuff, verbose() ))
错误
最高层消息
在HTTP请求中找到的MAC签名“Q8HvUVJLBJK+wkrIEG6LlsfFo19iDjneTwJxX/KXSnUCtTjgyyhYnH/5azeqa1bluGD94EcPcSRyBy2W2A/fHQ==”与任何计算出的签名都不相同。
响应内容
[1] "<?xml version=\"1.0\" encoding=\"utf-8\"?><Error>
<Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:1ab26da5-0001-00dc-6ddb-15e35c000000\nTime:2015-03-26T17:51:42.7190620Z</Message>
<AuthenticationErrorDetail>The MAC signature found in the HTTP request 'NTM1ODZjMjhhZmMyZGM3NDM0YTFjZDgwNGE0ODVmMzVjNDhkNjBkNzk1ZjNkZjJjOTNlNjUxYTMwMjRhNzNlYw==' is not the same as any computed signature. Server used following string to sign:
'GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Thu, 26 Mar 2015 17:52:37 GMT\nx-ms-version:2009-09-19\n/preconstuff/pings\ncomp:list\nrestype:container'.
</AuthenticationErrorDetail></Error>"
详细输出
-> GET /pings?restype=container&comp=list HTTP/1.1
-> User-Agent: curl/7.39.0 Rcurl/1.95.4.5 httr/0.6.1
-> Host: preconstuff.blob.core.windows.net
-> Accept-Encoding: gzip
-> Accept: application/json, text/xml, application/xml, */*
-> Authorization: SharedKey preconstuff:OTRhNTgzYmY3OTY3M2UzNjk3ODdjMzk3OWM3ZmU0OTA4MWU5NTE2OGYyZGU3YzRjNjQ1M2NkNzY0ZTcyZDRhYQ==
-> x-ms-date: Thu, 26 Mar 2015 17:56:27 GMT
-> x-ms-version: 2009-09-19
->
<- HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
<- Content-Length: 719
<- Content-Type: application/xml
<- Server: Microsoft-HTTPAPI/2.0
<- x-ms-request-id: 3d47770c-0001-0085-2313-6d466f000000
<- Date: Thu, 26 Mar 2015 17:56:27 GMT
<-
解决错误
通过谷歌搜索,似乎找不到一个一致的原因,但很可能是由于我方格式或请求结构不当所致。为此,我进行了以下检查:
- 我已验证我的密钥是正确的(它只是从门户中复制并粘贴)
- 我已确保日期格式正确
- 有一个最近的documentDB SO建议这可能是时钟偏差问题,我注意到我的x-ms-date比响应中的日期提前了一秒。我尝试发送一个明确在过去但在15分钟容差范围内的固定值。没有改变信息。
根据MSDN论坛问题,在headerstuff
中添加了encoding="Base64"
,但返回了相同的错误消息- 根据@Serdar的回答,我加入了构建签名字符串的过程(我已经验证这与错误消息中提供的签名字符串匹配),然后对UTF8转换的
signaturestring
进行hmac-sha256的base64编码(使用辅助访问密钥(sak
)作为加密密钥)作为SharedKey授权中要使用的值。 - 根据@Serdar的评论,签名字符串和主请求中使用的日期必须相同,因此定义一次并重复使用
有什么明显的问题吗?还有其他需要检查的事项吗?代码对其他人是否有效?