You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell实现HMAC-SHA256 API授权遇401错误求助

问题解决:PowerShell调用API的HMAC-SHA256授权401错误

问题概述

接手API调用任务,用PowerShell实现数据保存,已解决约束语言模式错误,但当前出现401未授权错误,核心问题出在HMAC-SHA256授权逻辑的实现偏差。

API授权规则(整理后)

生成签名密钥:

  1. 生成格式为“yyyyMMddTHHmmss”的UTC时间戳,与服务器时间差超10分钟请求会被拒绝;
  2. 使用私钥对上述时间戳生成HMAC-SHA256;
  3. 以上一步的二进制结果为密钥,对小写的API组件+公钥生成HMAC-SHA256,得到签名密钥。

请求签名:

  1. 用|拼接小写HTTP方法、小写请求URI绝对路径(不含域名和查询参数,含开头斜杠)、内容长度(GET请求填0),生成请求字符串;
  2. 用签名密钥对请求字符串生成HMAC-SHA256;
  3. 将结果Base64编码得到签名。

脚本中的核心错误及修正

错误1:时间戳未使用UTC时间

原脚本用本地时间生成时间戳,不符合API要求,会导致时间差校验失败。
修正:

$timestamp = (Get-Date -Utc -Format "yyyyMMddTHHmmss").ToString()

错误2:请求字符串中的URI错误

原脚本使用完整URL(包含域名),但API要求仅使用URI绝对路径(不含域名)。
修正:
提取URL中的路径部分,转小写:

# 提取URI路径部分
$uriPath = ([Uri]$uri).AbsolutePath.ToLower()
$requesttosign = $method.ToLower() + $seperator + $uriPath + $seperator + $contentlength

错误3:HMAC对象引用错误

原脚本使用未定义的$hmacsha1、$hmacsha3变量,会导致运行错误,且重复使用同一个HMAC对象可能存在状态污染。
修正:
每次计算哈希时,重新创建HMACSHA256对象,避免状态问题:

# step1key:用私钥对UTC时间戳生成HMAC-SHA256
$hmacshaStep1 = New-Object System.Security.Cryptography.HMACSHA256
$hmacshaStep1.Key = [Text.Encoding]::UTF8.GetBytes($apisecretkey)
$step1key = $hmacshaStep1.ComputeHash([Text.Encoding]::UTF8.GetBytes($timestamp))

# step2key:用step1key(二进制)作为密钥,对小写的component+apikey生成HMAC-SHA256
$hmacshaStep2 = New-Object System.Security.Cryptography.HMACSHA256
$hmacshaStep2.Key = $step1key  # 直接用二进制数组作为密钥,不要转UTF8
$step2key = $hmacshaStep2.ComputeHash([Text.Encoding]::UTF8.GetBytes(($component + $apikey).ToLower()))

# 生成签名:用step2key对请求字符串生成HMAC-SHA256后Base64编码
$hmacshaSign = New-Object System.Security.Cryptography.HMACSHA256
$hmacshaSign.Key = $step2key
$signatureBytes = $hmacshaSign.ComputeHash([Text.Encoding]::UTF8.GetBytes($requesttosign))
$signature = [Convert]::ToBase64String($signatureBytes)

错误4:Authorization头格式可能缺失必要信息

部分API要求Authorization头包含公钥、时间戳等额外信息,如果修正上述问题后仍报错,需确认API的头格式要求,比如添加时间戳到请求头:

$headers = @{
    Authorization = "Signature $signature"  # 或按API要求的格式调整
    "X-Timestamp" = $timestamp  # 若API要求传递时间戳
}

修正后的完整脚本

# Variables
$uri = "https://www.somewhere.com/api/uat/places/v1.1/lh/public/Properties"
$method = "GET"
$contentlength = "0"
$seperator = "|"
$timestamp = (Get-Date -Utc -Format "yyyyMMddTHHmmss").ToString()
$component = "keyword"

# API keys
$apikey = "thisisthekey"
$apisecretkey = "thisisthesecretkey"

# 生成请求字符串:提取URI路径,转小写
$uriPath = ([Uri]$uri).AbsolutePath.ToLower()
$requesttosign = $method.ToLower() + $seperator + $uriPath + $seperator + $contentlength

# 生成签名密钥 step1:私钥+时间戳
$hmacshaStep1 = New-Object System.Security.Cryptography.HMACSHA256
$hmacshaStep1.Key = [Text.Encoding]::UTF8.GetBytes($apisecretkey)
$step1key = $hmacshaStep1.ComputeHash([Text.Encoding]::UTF8.GetBytes($timestamp))

# 生成签名密钥 step2:step1key + 小写component+apikey
$hmacshaStep2 = New-Object System.Security.Cryptography.HMACSHA256
$hmacshaStep2.Key = $step1key
$step2key = $hmacshaStep2.ComputeHash([Text.Encoding]::UTF8.GetBytes(($component + $apikey).ToLower()))

# 生成最终签名
$hmacshaSign = New-Object System.Security.Cryptography.HMACSHA256
$hmacshaSign.Key = $step2key
$signatureBytes = $hmacshaSign.ComputeHash([Text.Encoding]::UTF8.GetBytes($requesttosign))
$signature = [Convert]::ToBase64String($signatureBytes)

# 构建请求头(若API要求,添加时间戳等额外字段)
$headers = @{
    Authorization = $signature  # 按API实际要求调整格式,比如"ApiKey $apikey:$signature"
    "X-Timestamp" = $timestamp
}

# 调用API并保存数据
try {
    $data = Invoke-RestMethod -Uri $uri -Method $method -Headers $headers
    $data | Export-Csv "\\server\location\data.csv" -NoTypeInformation
    Write-Host "数据保存成功"
}
catch {
    Write-Error "请求失败:$_"
}

学习资料参考

  • PowerShell中System.Security.Cryptography.HMACSHA256类用法:执行[System.Security.Cryptography.HMACSHA256] | Get-Member查看可用方法,或通过Get-Help了解.NET类文档。
  • UTC时间处理:使用Get-Date -Utc生成UTC时间,确保与服务器时间一致性。
  • URI路径提取:利用[Uri]类的AbsolutePath属性快速获取URL路径,避免手动截取出错。
  • HMAC哈希原理:理解二进制哈希值的处理逻辑,直接使用二进制数组作为密钥,不要随意转字符串再编码。

内容的提问来源于stack exchange,提问作者BarelySurviving

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 23:03:23