Ruby函数生成的HMAC-SHA256 $sb_token无效,IRB手动执行却正常?
问题排查与解决方案
核心排查方向
导致函数生成的令牌无效、手动执行却有效的常见原因集中在字符串换行符差异、全局变量值不一致以及签名计算细节偏差这几点,逐一排查如下:
修复换行符的硬编码问题
你代码中构建signature时用了硬换行:signature = encoded + ' ' + ttl这种写法会让字符串中包含当前系统的换行符(Windows是
\r\n,Unix是\n),而手动在IRB中执行时你大概率是写的encoded + "\n" + ttl,统一用\n换行符才符合Service Bus签名要求。修改为:signature = "#{encoded}\n#{ttl}"验证全局变量的一致性
函数依赖$resourceUri、$sasKeyName、$sasKey三个全局变量,务必确认函数执行时这些变量的值和你手动在IRB中测试时完全一致。可以在函数开头添加打印语句:puts "resourceUri: #{$resourceUri}" puts "sasKeyName: #{$sasKeyName}" puts "sasKey: #{$sasKey}"对比手动执行时的输出,避免函数调用前全局变量被意外修改。
逐字符对比令牌差异
分别打印函数生成的$sb_token和手动生成的令牌,对比每一部分:sr部分的URL编码是否一致sig部分的Base64编码结果是否相同se的时间戳是否在有效期内(虽然40103是签名错误,但也要排除时间差导致的问题)
重点看sig,只要这里有差异,签名就会验证失败。
替换全局变量为函数参数(推荐)
全局变量容易引发不可预见的副作用,把参数传入函数能彻底避免这类问题:def get_service_bus_token(resource_uri, sas_key_name, sas_key) encoded = ERB::Util.url_encode(resource_uri) now = Time.now.to_i ttl = (now + 60).to_s signature = "#{encoded}\n#{ttl}" digest = OpenSSL::Digest.new('sha256') hmac = OpenSSL::HMAC.digest(digest, sas_key, signature) hash = Base64.strict_encode64(hmac) "SharedAccessSignature sr=#{encoded}&sig=#{ERB::Util.url_encode(hash)}&se=#{ttl}&skn=#{sas_key_name}" end调用时直接传入参数:
$sb_token = get_service_bus_token($resourceUri, $sasKeyName, $sasKey)
验证方法
修改后,先在IRB中调用函数生成令牌,和手动步骤生成的令牌对比,确认完全一致后再发起HTTP请求。
内容的提问来源于stack exchange,提问作者J. Naylor
相关产品推荐
相关产品推荐

