Python 谷歌云存储URL签名

Python 谷歌云存储URL签名,python,elixir,google-cloud-storage,Python,Elixir,Google Cloud Storage,我有一个签名者,它非常适合从地面军事系统上传和下载。伟大的签名者如下所示: def sign_url(client, bucket, key, opts \\ []) do verb = opts[:verb] || "GET" md5_digest = opts[:md5_digest] || "" content_type = opts[:content_type] || "" expires = opts[:expires] || Utils.years(10) res

我有一个签名者,它非常适合从地面军事系统上传和下载。伟大的签名者如下所示:

def sign_url(client, bucket, key, opts \\ []) do
  verb = opts[:verb] || "GET"
  md5_digest = opts[:md5_digest] || ""
  content_type = opts[:content_type] || ""
  expires = opts[:expires] || Utils.years(10)
  resource = "/#{bucket}/#{key}"

  signature =
    [verb, md5_digest, content_type, expires, resource]
    |> Enum.join("\n")
    |> generate_signature(client)

  url = "#{@base_url}#{resource}"

  qs =
    %{
      "GoogleAccessId" => client.client_email,
      "Expires" => expires,
      "Signature" => signature
    }
    |> URI.encode_query()

  Enum.join([url, "?", qs])
end

defp generate_signature(string, client) do
  private_key = get_private_key(client)

  string
  |> :public_key.sign(:sha256, private_key)
  |> Base.encode64()
end

defp get_private_key(client) do
  client.private_key
  |> :public_key.pem_decode()
  |> Kernel.hd()
  |> :public_key.pem_entry_decode()
end
我遇到的问题是,是否要添加
x-goog
标题,例如
x-goog-copy-source
。这样做,我会得到一个错误:

The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.
现在,我知道签名URL支持自定义标题,但我不确定如何更新签名以支持它。我在网上找不到任何描述这一点的资源,包括谷歌文档

还有其他人有过这样的经历吗


谢谢

我稍微修改了你的代码以添加标题。他们应该在字符串过期后签名

我对长生不老药不太了解,但希望这能为你指明正确的方向。它基于Ruby存储实现()

编辑:可以找到有关此构造的文档


我对您的代码进行了一些修改,以添加标题。他们应该在字符串过期后签名

我对长生不老药不太了解,但希望这能为你指明正确的方向。它基于Ruby存储实现()

编辑:可以找到有关此构造的文档


谢谢,这正是问题所在。我在发帖后一个小时就发现了这个问题,但由于这是一个正确的答案,所以我提高了投票率。谢谢你让我们知道!干杯汉克斯,这正是问题所在。我在发帖后一个小时就发现了这个问题,但由于这是一个正确的答案,所以我提高了投票率。谢谢你让我们知道!干杯
def sign_url(client, bucket, key, opts \\ []) do
  verb = opts[:verb] || "GET"
  md5_digest = opts[:md5_digest] || ""
  content_type = opts[:content_type] || ""
  expires = opts[:expires] || Utils.years(10)
  resource = "/#{bucket}/#{key}"
  headers = 
    Enum.map(opts[:headers], fn ({key, value}) -> "#{key}:#{value}" end)
           |> Enum.join("\n")

  signature =
    [verb, md5_digest, content_type, expires, headers, resource]
    |> Enum.join("\n")
    |> generate_signature(client)

  url = "#{@base_url}#{resource}"

  qs =
    %{
      "GoogleAccessId" => client.client_email,
      "Expires" => expires,
      "Signature" => signature
    }
    |> URI.encode_query()

  Enum.join([url, "?", qs])
end

defp generate_signature(string, client) do
  private_key = get_private_key(client)

  string
  |> :public_key.sign(:sha256, private_key)
  |> Base.encode64()
end

defp get_private_key(client) do
  client.private_key
  |> :public_key.pem_decode()
  |> Kernel.hd()
  |> :public_key.pem_entry_decode()
end