我有一个签名者,非常适合从GCS上载和下载。大!签名者看起来像这样:
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支持自定义标头,但是我不确定如何更新签名以支持它。我找不到包括该文档在内的在线资源,包括Google文档。
其他人对此有经验吗?
谢谢
答案 0 :(得分:2)
我稍微修改了您的代码以添加标题。期望它们在字符串中过期后才能签名。
我对Elixir的了解还不够,但是希望这可以为您指明正确的方向。它基于Ruby存储实现(https://github.com/googleapis/google-cloud-ruby/blob/master/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb#L62)
编辑:可以在here中找到有关此构造的文档。
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