方括号打破了OAuth签名的生成-如何对其进行编码?

时间:2018-11-30 10:52:43

标签: ruby oauth openssl

我正在使用Ruby为使用OAuth的网站生成OAuth签名。到目前为止,它一直工作良好,直到我尝试用方括号添加一些参数。现在,我收到“签名不匹配”的错误信息。

我的猜测是,当Oauth生成签名时,它处理方括号的方式与生成签名时处理方括号的方式不同。

这就是我生成OAuth信号(在Ruby中)的方式:

oauth_params = {
  "oauth_consumer_key" => options["key"], #oAuth Consumer Key
  "oauth_nonce" => MiscUtilities.generate_nonce, #oAuth Nonce - just a random numnber
  "oauth_signature_method" => "HMAC-SHA1", #oAuth Signature Method - don't need to change this
  "oauth_timestamp" => Time.now.to_i.to_s, #oAuth Timestamp, standard seconds since epoch.
  "oauth_version" => "1.0" #oAuth Version - don't need to change this
}
#add any other non-oauth params we've been given
params = oauth_params.merge(options["params"])

#sort and url encode the params
encoded_params = params.sort_by{|k,v| k.to_s}.collect { |k, v| CGI.escape("#{k.to_s}=#{v}") }.join('%26')
signature_base_string = "#{options["method"]}&#{CGI.escape(options["api_url"])}&#{encoded_params}"
signing_key = "#{options["secret"]}&" 

#generate the signature and add it to params
digest = OpenSSL::Digest::Digest.new('sha1')
hmac = OpenSSL::HMAC.digest(digest, signing_key, signature_base_string)
params["oauth_signature"] = Base64.encode64(hmac).chomp
params  

就像我说的那样,在我添加方括号之前,这一直很好。

有人在上面遇到过这个问题,或者能够看到我做错了什么吗?

3 个答案:

答案 0 :(得分:1)

您不应在URL或整个键值对上使用CGI:Escape。应该在键上使用它,并在值上单独使用它。然后将这两个以等号连接起来,然后将这些对添加到以&分隔的查询字符串中。

说到这里-我看到您正在加入'%26'(编码为&)。除非您的基本值不需要编码,否则这似乎不符合规范。这相当于“编码”值,然后编码整个字符串。也许这就是括号引起问题的原因-将括号添加到值后,就需要对该值进行编码。

 encoded_params = Map [params.map {|k, v| CGI.Escape(k), CGI.Escape(v)}]
                  .sort_by{|k,v| k.to_s}
                  .collect { |k, v| CGI.escape("#{k.to_s}=#{v}") }
                  .join('%26')

我不是一个红宝石专家-我只是从一个处理哈希值的答案中举了一个例子,并将其应用于此处。请做一些必要的工作以制作正确的红宝石代码。我还保留了其余的代码。虽然可能会造成混淆,但似乎可以完成工作。

还有另一个潜在的问题-根据规范,完成的URI编码可能与普通URI编码略有不同。空格为%20,而不是+,并且必须对除ALPHA,DIGIT,'_','-','。'和'〜'以外的所有内容进行编码,并且不得对这些值进行编码。那是否适用于CGI:Escape?我没有安装ruby,对规范的快速检查使我找到了一个单行文档。

edit:上面的算法不适用于需要编码的事物,因为来自被编码事物的%也会被 编码。只需稍作调整即可对整个值进行编码,而不必与编码后的与号结合在一起。

答案 1 :(得分:0)

技巧是必须将签名基本字符串中的方括号转换两次:

  • [=>%5B =>%255B
  • ] =>%5D =>%255D

答案 2 :(得分:0)

我最终这样做了,我认为这不是特别干净,但是确实可以。

CASE WHEN  d.receipt IS NULL AND c.receipt =1 then pr.account END ASC,
CASE WHEN  d.receipt =1 AND c.receipt IS NULL then pr.account END ASC,
CASE WHEN  d.receipt =1 AND c.receipt =0 then pr.account END ASC,
CASE WHEN  d.receipt =1 AND c.receipt =1 then pr.account END ASC,

CASE WHEN  d.receipt IS NULL AND c.receipt IS NULL THEN pr.amount END DESC,
CASE WHEN  d.receipt IS NULL AND c.receipt =0 THEN pr.amount END DESC,
CASE WHEN  d.receipt =0 AND c.receipt IS NULL THEN pr.amount END DESC,
CASE WHEN  d.receipt =0 AND c.receipt =0 THEN pr.amount END DESC,
CASE WHEN  d.receipt =0 AND c.receipt =1 THEN pr.amount END DESC