我正在尝试使用自定义ruby代码(从官方php库移植到azure)为我的Windows媒体服务文件创建SAS URL。代码看起来像这样:
def create_signature(path = '/', resource = 'b', permissions = 'r', start = '', expiry = '', identifier = '')
# If resource is a container, remove the last part (which is the filename)
path = path.split('/').reverse.drop(1).reverse.join('/') if resource == 'c'
canonicalizedResource = "/mediasvc78m7lfh2gnn2x/#{path}"
stringToSign = []
stringToSign << permissions
stringToSign << start
stringToSign << expiry
stringToSign << canonicalizedResource
stringToSign << identifier
stringToSign = stringToSign.join("\n")
signature = OpenSSL::HMAC.digest('sha256', wms_api_key, stringToSign.encode(Encoding::UTF_8))
signature = Base64.encode64(signature)
return signature
end
def createSignedQueryString(path = '/', query_string = '', resource = 'b', permissions = 'r', start = '', expiry = '', identifier = '')
base = 'https://mediasvc78m7lfh2gnn2x.blob.core.windows.net'
uri = Addressable::URI.new
# Parts
parts = {}
parts[:st] = URI.unescape(start) unless start == ''
parts[:se] = URI.unescape(expiry)
parts[:sr] = URI.unescape(resource)
parts[:sp] = URI.unescape(permissions)
parts[:si] = URI.unescape(identifier) unless identifier == ''
parts[:sig] = URI.unescape( create_signature(path, resource, permissions, start, expiry) )
uri.query_values = parts
return "#{base}/#{path}?#{uri.query}"
end
运行时:
puts createSignedQueryString(
'asset-12514a3b-565f-4150-9543-e3c2b4531428/video.mp4',
nil,
'b',
'r',
(Time.now - 5*60).utc.iso8601,
(Time.now + 30*60).utc.iso8601
)
当我尝试将浏览器指向它时,我得到了:
<Error>
<Code>AuthenticationFailed</Code>
<Message>
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:ee7fd18f-cd1f-4179-8a58-c8b746d0549c Time:2014-02-20T12:29:27.0468171Z
</Message>
<AuthenticationErrorDetail>
Signature did not match. String to sign used was r 2014-02-20T12:24:19Z 2014-02-20T12:59:19Z /mediasvc78m7lfh2gnn2x/asset-12514a3b-565f-4150-9543-e3c2b4531428/video.mp4
</AuthenticationErrorDetail>
</Error>
您是否知道可能导致该错误的原因(或如何调试?)以及如何处理?提前谢谢。
答案 0 :(得分:2)
假设您直接从门户网站使用存储密钥并在wms_api_key
变量中使用该存储密钥(或者换句话说,您的wms_api_key
是Base64编码的字符串,我相信您需要转换它首先作为用于计算签名的字节数组。您需要执行以下操作:
signature = OpenSSL::HMAC.digest('sha256', Base64.strict_decode64(wms_api_key), stringToSign.encode(Encoding::UTF_8))
这是基于Github上Azure SDK for Ruby
的源代码。
<强>更新强>
我发现了另外一个问题。如果您注意到SAS URL,您会注意到%0A
查询字符串参数末尾的sig
,这实际上是一个新的行字符。不知道为什么会这样,但我认为当你执行以下操作时它会自动插入:
signature = Base64.encode64(signature)
但是,如果我使用strict_encode64
代替encode64
方法,则不会插入,并且一切都很好。请尝试以下代码:
signature = Base64.strict_encode64(signature)
我只是尝试过它,它对我很有用。