使用 GET 请求对表单数据签名的奇怪行为

Weird behavior on form data signature with a GET request

案例研究

我有 2 个应用程序(Rails => 发送方和 Laravel => 接收方),我在其中使用私钥和 public 密钥对数据进行签名,以确保请求之间信息的准确性。使用 GET 参数将数据从一个应用程序发送到另一个应用程序:

domain.com/callback?order_id=12&time=2015-10-01T22:38:20Z&signature=VX2WxlTaGK5N12GhZ5oqXU5h3wW/I70MYZhLbAYNQ79pFquuhdOerwBwqaq2BRuGyhKoY6VEHJkNnFjLAJkQD6Q5z4Vmk...

问题

我在 staging 服务器和 local 服务器之间遇到关于这些数据签名的奇怪行为。

在分段测试时,生成 link (GET) 看起来像(来自 chrome 的源代码):

而在本地服务器上,它的格式完全相同 html(当然除了数据发生变化)。顺便说一下,我正在使用 HAML

回调 URL 由装饰器生成:

def url_to_store
  params    = url_params.to_a.map { |a| a.join('=') }.join('&')
  signature = Shield::Crypto.new(params).signature
  "#{object.referer}?#{params}&signature=#{signature}"
end

def url_params
  {
    order_id:       object.id,
    transaction_id: object.transaction_id,
    user_id:        object.user_id,
    status:         object.status,
    time:           Time.now.utc.iso8601,
    reference:      object.success? ? object.reference : ''
  }
end

在暂存中单击 link 时,我被重定向到实际验证签名的其他应用程序。一切正常。

但是,同样的事情不适用于语言环境服务器(我的机器)。单击 link 时,签名包含空格 (%20) :

signature=wP5EmeIGzXynwJc+BDV+jGVzyYhZOJuu7PzCXgnP2qbBfdqrAceEjxgh1EH2%20%20%20%20%20%20%20%20%20%20%20%20tvR66o3IA

这当然会使其他应用程序拒绝请求,因为签名无效。 这是我的问题。完全相同的应用程序。完全相同的代码库和版本(a.k.a commit sha)。不同的行为。

我不知道如何重现它。我希望你们中的一些人已经经历过类似的情况并且可以给我一个提示。

想法?

注意:我正在使用完全相同的回调 url(本地 PHP 应用程序)来测试登台和本地服务器。我不认为问题来自 PHP 应用程序。可能与 Rails 调试相关的东西?

问题出在 Haml 并且是 ugly 模式。在 development 中,它默认设置为 false,这会导致 HTML 代码被填充并且不知何故弄乱了签名。

已在此处找到相关的 github 问题 https://github.com/haml/haml/issues/636 and here https://github.com/haml/haml/issues/828

所以为了修复它,我创建了一个初始化程序来默认启用它:

config/initializers/haml.rb

require 'haml/template'
Haml::Template.options[:ugly] = true