You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Blob下载SAS Token验证失败:签名不匹配问题求助

Azure Blob SAS URL生成出现「Signature did not match」问题排查

我用Ruby生成Azure Blob的SAS URL,示例URL如下:

https://anasstoragetest2023.blob.core.windows.net/telestream/test.mov?sp=r&st=2023-03-14T20:23:04Z&se=2023-03-18T20:23:04Z&spr=https&sv=2021-12-02&sr=b&sig=6wpeYAlfpnGLPtk5PcIe/P+0q+XeLkIT6XLFR6uY5Os=

遇到「Signature did not match」错误,错误详情:

<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:0daa3721-e01e-0002-3049-58f5bf000000 Time:2023-03-16T20:55:10.7515529Z</Message>
   <AuthenticationErrorDetail>Signature did not match. String to sign used was r 2023-03-14T20:52:54Z 2023-03-18T20:52:54Z /blob/anasstoragetest2023/telestream/test.mov https 2021-12-02 b </AuthenticationErrorDetail>
  </Error>

我的代码输出的签名字符串和错误日志里的完全一致:

String to sign: r 2023-03-14T20:52:54Z 2023-03-18T20:52:54Z /blob/anasstoragetest2023/telestream/test.mov   https 2021-12-02 b      

尝试过Azure官方的SAS生成器,生成的token同样报这个错,代码如下:

blob_path = "/blob/#{account_name}/#{container_name}/#{blob_name}"
signature = 
    Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(account_name, account_key)
sas_token = 
    signature.generate_service_sas_token(blob_path, service: 'b', resource: 'b')

puts "\nCreated SAS token: #{sas_token}"
url = "https://#{account_name}.blob.core.windows.net/#{container_name}/#{blob_name}?#{sas_token}"
puts "\nCreated URL: #{url}"

以下是我自己写的Ruby代码,试过Ruby 3.1.3和2.6.8版本,依赖通过gem install azure-storage-blob安装,求解决:

def generate_blob_url(account_name, account_key, container_name, blob_name)
start_time = Time.now
days = 60*60*24*2

signed_permissions = "r"
signed_start = (start_time - days).utc.iso8601
signed_expiry = (start_time + days).utc.iso8601
canonicalized_resource = "/blob/#{account_name}/#{container_name}/#{blob_name}"
signed_identifier = ""
signed_ip = ""
signed_protocol = "https"
signed_version = "2021-12-02" # "2018-11-09"
signed_resource = "b"
signed_snapshottime = ""
rscc = ""
rscd = ""
rsce = ""
rscl = ""
rsct = ""

string_to_sign = signed_permissions + "\n" +
      signed_start + "\n" +
      signed_expiry + "\n" +
      canonicalized_resource + "\n" +
      signed_identifier + "\n" +
      signed_ip + "\n" +
      signed_protocol + "\n" +
      signed_version + "\n" +
      signed_resource + "\n" +
      signed_snapshottime + "\n" +
      rscc + "\n" +
      rscd + "\n" +
      rsce + "\n" +
      rscl + "\n" +
      rsct

puts "\nString to sign: #{string_to_sign.gsub("\n", " ")}"
sig = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', account_key, string_to_sign))
token = "sp=#{signed_permissions}&st=#{signed_start}&se=#{signed_expiry}&spr=#{signed_protocol}&sv=#{signed_version}&sr=#{signed_resource}&sig=#{sig}"
puts "\nGenerated token: #{token}"

url = "https://#{account_name}.blob.core.windows.net/#{container_name}/#{blob_name}?#{CGI.escape(token)}"
end

解决建议

  1. 解码账户密钥后再计算签名
    Azure存储账户密钥是Base64编码格式,直接用字符串计算HMAC会导致签名错误,需要先解码为原始字节:
decoded_account_key = Base64.decode64(account_key)
sig = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', decoded_account_key, string_to_sign))
  1. 避免SAS Token整体编码
    你当前用CGI.escape(token)会把Base64签名里的+、/等字符转义成%2B、%2F,Azure无法识别转义后的字符,应该直接拼接token:
url = "https://#{account_name}.blob.core.windows.net/#{container_name}/#{blob_name}?#{token}"
  1. 严格控制签名字符串格式
    确保签名字符串里的空参数(如signed_identifier、signed_ip)仅保留单个换行符,没有多余空格。代码中gsub("\n", " ")只是用于打印显示,实际生成的string_to_sign要严格按照参数顺序用\n分隔。

  2. 验证官方生成器的密钥传入方式
    使用官方生成器时,同样要确保传入的account_key是解码后的原始字节,避免直接使用Base64字符串。

内容的提问来源于stack exchange,提问作者anode84

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:09:56