博士
生成**$sb_token全局变量(这是一个HMAC-SHA 256密钥)的函数似乎不能正确/准确地生成它,而如果我手动运行函数中的步骤,它会正确/准确地生成它。
我在IRB中调试Ruby脚本,遇到了一个奇怪的问题。
也许你会告诉我,我用错了变量,我很高兴能接受教育,但我不明白这里发生了什么。
我有一个函数,它生成了$sb_token**变量(我并不完全理解OpenSSL / Base64 / hmac的所有用法,但我已经证明了这一点):
def get_service_bus_token()
resourceUri = $resourceUri
sasKeyName = $sasKeyName
sasKey = $sasKey
# url encoded
encoded = ERB::Util.url_encode(resourceUri)
# ttl
timeNow = Time.now; $sb_token_timestamp = timeNow
now = timeNow.to_i
minute = 60
ttl = ((now ) + minute).to_s;
#ttl = 1646428676.to_s
# sig
signature = encoded + '
' + ttl
digest = OpenSSL::Digest.new('sha256')
hmac = OpenSSL::HMAC.digest(digest, sasKey, signature)
#hmac = OpenSSL::HMAC.hexdigest(digest, sasKey, signature)
hash = Base64.strict_encode64(hmac)
$sb_token = "SharedAccessSignature sr=" + encoded + "&sig=" + ERB::Util.url_encode(hash) + "&se=" + ttl + "&skn=" + sasKeyName;
return $sb_token
end
当我执行上面的 get_service_bus_token() 函数时,$sb_token对象被创建并存储为全局变量。
我在另一个函数中使用**$sb_token对象作为Authorization头:headers['Authorization'] = $sb_token
然后用这个头发出请求:response = HTTParty.post(url, :headers=>headers, :body=>body )
这不起作用-我收到无效授权令牌响应:#<Net::HTTPUnauthorized 401 SubCode=40103: Invalid authorization token signature readbody=true>
然而,这是令人困惑的部分。
如果我手动运行 get_service_bus_token() 函数中的步骤(即将它们复制并粘贴到IRB中),从而创建$sb_token对象,如下所示:$sb_token = "SharedAccessSignature sr=" + encoded + "&sig=" + ERB::Util.url_encode(hash) + "&se=" + ttl + "&skn=" + sasKeyName;
然后当我执行这些步骤,它的工作!!!headers['Authorization'] = $sb_token
response = HTTParty.post(url, :headers=>headers, :body=>body )
#<Net::HTTPCreated 201 Created readbody=true>
这让我很困惑。
本质上,生成$sb_token**全局变量的函数似乎不能正确/准确地生成它,而如果我手动运行函数中的步骤,它会正确/准确地生成它。
这让我觉得是一个问题,要么a)全局变量的使用,要么b)在IRB提示符上创建函数vs内部生成的字符串是不同的。
有人有什么线索吗?
1条答案
按热度按时间yh2wf1be1#
如果不了解应用程序的其余部分是如何构建的,很难确定。但是我可以告诉你,使用全局变量是一种不好的做法,可能会导致各种各样的问题,这些问题与你在这里描述的问题非常相似。你可以在这里和其他地方阅读有关ruby global variable问题的内容。
全局变量在多线程应用程序中的所有线程之间共享。如果您有两个线程同时运行,并且设置全局变量的值,那么您将遇到争用条件。例如,您在此方法的末尾设置
$sb_token
;如果两个线程同时调用这个方法,那么这个全局值将被最后一个运行的线程覆盖。Ruby线程调度可能意味着它按以下顺序执行:1.第一个线程调用将
$sb_token
设置为值A的方法1.第二个线程调用将
$sb_token
设置为值B的方法1.第二个线程使用值为B的
$sb_token
运行后续方法1.第一个线程使用值为B(不是A)的
$sb_token
运行后续方法同样,你在方法开始时使用的变量很可能在应用程序的其他地方设置,它们也会遇到同样的问题。
在IRB中看不到这些错误的原因是因为IRB是单线程的,当只有一个线程时,不可能有并发问题。
我不能直接给予你如何在没有全局变量的情况下构造你的应用程序,因为我不知道它的其余部分是什么样子的,例如,如果你使用类和类示例。但通常你应该看看encapsulation作为指导。你可能想通过将变量用作方法的参数来封装它们,就像这样:
或者将它们设置为示例变量:
但作为最佳实践,你应该在几乎所有情况下避免使用全局变量和类变量,除非你清楚地了解它们的工作原理以及为什么需要使用它们。
最后,我建议你阅读链接中的Ruby样式指南。其中有一些技巧,你应该考虑遵循,以使你的代码更加地道,例如:
1.用于符号、方法和变量的Snake Case
1.我应该用
;
终止表达式吗?1.压痕