尝试使用 PowerShell 列出 Azure 文件服务中的共享时身份验证失败

Authentication Failure when trying to list shares in Azure Files service using PowerShell

我正在尝试通过使用 Invoke-RestMethod 点击 REST API 使用 PowerShell 对 Azure 文件预览进行身份验证。我正在尽力按照此处提供的说明进行操作:https://msdn.microsoft.com/en-us/library/azure/dd179428.aspx

这是我的脚本:

$accountname = "testaccount"
$xmsdate = get-date
$xmsdate = $xmsdate.addhours(6)
$xmsdate = $xmsdate.toString('r')
$accesskey = 'lfksZQh0nasdfasd0KeMI+1alslv8ukK39Rsoelsldiq1r+zed9r4bH5uRyba+/QCwwvdGotw=='
$message = "GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:" + $xmsdate + "\nx-ms-version:2014-02-14\n/" + $accountname + "/ comp:list\nrestype:share\ntimeout:20"

$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($accesskey)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($message))
$signature = [Convert]::ToBase64String($signature)
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("x-ms-version", '2014-02-14')
$headers.Add("x-ms-date", $xmsdate)
$headers.Add("Authorization", "SharedKey " + $accountname + ":" + $signature)
$uri = "http://" + $accountname + ".file.core.windows.net/?comp=list"
invoke-restmethod -Uri $uri -Headers $headers

我收到的错误是“在 HTTP 请求中找到的 MAC 签名...与任何签名都不一样 计算签名。服务器使用以下字符串进行签名:'GET x-ms-date:Wed, 11 Feb 2015 23:25:06 GMT x-ms-version:2014-02-14 /testaccount/ comp:list"

我从这里找到了加密消息的代码:https://gist.github.com/jokecamp/2c1a67b8f277797ecdb3

我发现了一些事情:

  • Date/Time UTC

    $xmsdate = 获取日期
    $xmsdate = $xmsdate.addhours(6)
    $xmsdate = $xmsdate.toString('r')

因为 date/time 必须是 UTC,更好的方法是这样的:

$xmsdate = get-date
$xmsdate = $xmsdate.ToUniversalTime()
$xmsdate = $xmsdate.toString('r')
  • “\n”导致问题

换行符不要使用 \n,而是使用“$([char]10”或“`n”(https://twitter.com/gmantri/status/565694148637097984)

$newLine = $([char]10);
$message = "GET" + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + "x-ms-date:" + $xmsdate + $newLine + "x-ms-version:2014-02-14" + $newLine + "/" + $accountname + "/" + $newLine + "comp:list";
  • 使用Convert.FromBase64String将账户密钥转换为字节数组

    $hmacsha = 新对象 System.Security.Cryptography.HMACSHA256;

    $hmacsha.key = [转换]::FromBase64String($accesskey);

  • URL 和签名计算中的查询字符串参数必须相同:在您的情况下,您包括 timeout签名计算中的参数,但未在 URL 查询字符串中提供。

基于这些,请尝试以下脚本:

$accountname = "accountname"
$xmsdate = get-date
$xmsdate = $xmsdate.ToUniversalTime()
$xmsdate = $xmsdate.toString('r')
$accesskey = 'accountkey'
$newLine = $([char]10);
$message = "GET" + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + $newLine + "x-ms-date:" + $xmsdate + $newLine + "x-ms-version:2014-02-14" + $newLine + "/" + $accountname + "/" + $newLine + "comp:list";
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Convert]::FromBase64String($accesskey)
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($message))
$signature = [Convert]::ToBase64String($signature)
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("x-ms-version", "2014-02-14")
$headers.Add("x-ms-date", $xmsdate)
$headers.Add("Authorization", "SharedKey " + $accountname + ":" + $signature)
$uri = "http://" + $accountname + ".file.core.windows.net/?comp=list"
invoke-restmethod -Uri $uri -Headers $headers

PowerShell 中的换行符是 `n 而不是 \n。 :)

$message = "GET`n`n`n`n`n`n`n`n`n`n`n`nx-ms-date:" + $xmsdate + "`nx-ms-version:2014-02-14`n/" + $accountname + "/ comp:list`nrestype:share`ntimeout:20"