rest - 使用 Elixir 和 HTTPoison 访问 Azure 存储服务 REST API

标签 rest azure elixir azure-storage httpoison

我正在尝试使用 Elixir 访问 Azure Storage Services via their REST API但我很难获得 Authentication Header上类。如果我使用ex_azure,我就可以连接包( erlazure 的包装器),但当我尝试构建请求并使用 HTTPoison 时则不会.

最近的错误消息

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Error>
  <Code>AuthenticationFailed</Code>
  <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:00000000-0000-0000-0000-000000000000\nTime:2017-08-02T21:46:08.6488342Z</Message>
  <AuthenticationErrorDetail>The MAC signature found in the HTTP request '<signature>' is not the same as any computed signature. Server used following string to sign: 'GET\n\n\nWed, 02 Aug 2017 21:46:08
    GMT\nx-ms-date-h:Wed, 02 Aug 2017 21:46:08 GMT\nx-ms-version-h:2017-05-10\n/storage_name/container_name?comp=list'.</AuthenticationErrorDetail>
</Error>

第一次编辑后

  <?xml version=\"1.0\" encoding=\"utf-8\"?>
  <Error>
    <Code>AuthenticationFailed</Code>
    <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:00000000-0000-0000-0000-000000000000\nTime:2017-08-03T03:03:57.1385277Z</Message>
    <AuthenticationErrorDetail>The MAC signature found in the HTTP request '<signature>' is not the same as any computed signature. Server used following string to sign: 'GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Thu, 03 Aug
      2017 03:03:57 GMT\nx-ms-version:2017-04-17\n/storage_name/container_name\ncomp:list\nrestype:container'.</AuthenticationErrorDetail>
  </Error>

依赖项

# mix.exs
defp deps do
  {:httpoison, "~> 0.12"}
  {:timex, "~> 3.1"}
end

代码

  • 我是否正确设置了身份验证 header (string_to_sign) 的格式?
  • 我使用的编码/解码正确吗?
  • 我是否正确向 HTTPoison 添加 header ?
  • 我是否应该使用其他内容来执行 REST 操作而不是 HTTPoison?
# account credentials
storage_name            = "storage_name"
container_name          = "container_name"
storage_key             = "storage_key"
storage_service_version = "2017-04-17" # fixed version

request_date =
  Timex.now
  |> Timex.format!("{RFC1123}") # Wed, 02 Aug 2017 00:52:10 +0000
  |> String.replace("+0000", "GMT") # Wed, 02 Aug 2017 00:52:10 GMT

# set canonicalized headers
x_ms_date    = "x-ms-date:#{request_date}"
x_ms_version = "x-ms-version:#{storage_service_version}"

# assign values for string_to_sign
verb                   = "GET\n"
content_encoding       = "\n"
content_language       = "\n"
content_length         = "\n"
content_md5            = "\n"
content_type           = "\n"
date                   = "\n"
if_modified_since      = "\n"
if_match               = "\n"
if_none_match          = "\n"
if_unmodified_since    = "\n"
range                  = "\n"
canonicalized_headers  = "#{x_ms_date}\n#{x_ms_version}\n"
canonicalized_resource = "/#{storage_name}/#{container_name}\ncomp:list\nrestype:container" # removed timeout. removed space

# concat string_to_sign
string_to_sign =
  verb                  <>
  content_encoding      <>
  content_language      <>
  content_length        <>
  content_md5           <>
  content_type          <>
  date                  <>
  if_modified_since     <>
  if_match              <>
  if_none_match         <>
  if_unmodified_since   <>
  range                 <>
  canonicalized_headers <>
  canonicalized_resource

# decode storage_key
{:ok, decoded_key} =
  storage_key
  |> Base.decode64

# sign and encode string_to_sign
signature =
  :crypto.hmac(:sha256, decoded_key, string_to_sign)
  |> Base.encode64

# build authorization header
authorization_header = "SharedKey #{storage_name}:#{signature}"

# build request and use HTTPoison
url     = "https://storage_name.blob.core.windows.net/container_name?restype=container&comp=list"
headers = [ # "Date": request_date,
           "x-ms-date": request_date, # fixed typo
           "x-ms-version": storage_service_version, # fixed typo
           # "Accept": "application/json",
           "Authorization": authorization_header]
options = [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500]

HTTPoison.get(url, headers, options)

注释

我使用/尝试过的一些来源...

最佳答案

我注意到的一些问题:

  1. 您在请求中包含了 Date 请求 header ,但它未包含在您的 string_to_sign 中。将此 header 包含在您的 string_to_sign 中,或从请求 header 中删除此 header 。
  2. 您在 canonicalized_resource 中添加了 timeout:30,但它并未包含在您的请求网址中。同样,在请求查询字符串中添加 timeout=30 或从 canonicalized_resource 中删除 timeout:30
  3. 我没有使用过 Elixir,所以我不知道请求 header 是如何工作的,但您将请求 header 命名为 x-ms-date-hx -ms-版本-h。它们不应该分别是 x-ms-datex-ms-version 吗?

关于rest - 使用 Elixir 和 HTTPoison 访问 Azure 存储服务 REST API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45472216/

相关文章:

javascript - 尝试在 https ://api. thetvdb.com/向 TVDB REST API 发出 JSON POST 请求,但收到 CORS 错误

java - 阻塞非 CRUD REST 动词

erlang - Elixir 紧循环加速

linux - 带有 sudo 和 System.cmd ("mount"的 IEx block )

web-services - HTTPS 身份验证会减慢我的应用程序吗?

azure - 在 Visual Studio 2022 中使用 .NET 6 远程调试 Azure Web 作业

azure - 在 KQL 中使用按时间戳汇总获取上次登录详细信息

使用 DeployIfNotExists 策略对私有(private) dns 区域组进行 Azure Terraformignore_changes

cucumber - 隔离 Cabbage 中的场景

mysql - 从 Docker 容器中访问主机上的 MySQL 数据库