.NET Core HttpClient调用WooCommerce API遇OAuth 401无效签名问题
WooCommerce OAuth 1.0签名无效(401未授权)排查与修复
以下是导致签名验证失败的核心问题及修复方案:
1. 请求头语法错误
代码中oauth_signature_method=\"HMAC-SHA1'使用单引号闭合,应为双引号,导致服务器无法正确解析参数。
2. 签名基字符串构建逻辑错误
OAuth 1.0要求:
- 所有OAuth参数需按字典序排序
- 拼接成
key=value&key=value格式后整体URL转义
而非每个参数单独转义后拼接,否则会导致参数间的&处理异常,破坏签名的正确性。
3. 请求URL与签名基字符串URL不一致
签名基字符串中的URL是https://loomina.ir/wp-json/wc/v3/products(无末尾斜杠),但实际请求URL带末尾斜杠,URL规范化必须完全一致,否则签名验证不通过。
4. Authorization头参数分隔符缺失空格
OAuth头参数需用, (逗号加空格)分隔,而非直接逗号,部分服务器对格式要求严格,会导致参数解析失败。
修正后的代码
生成OAuth签名头方法
public static string GetoAuthToken(string conKey, string conSecret, string requestUrl) { // 生成标准Unix时间戳(秒级) long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); string timestampStr = timestamp.ToString(); // 生成唯一Nonce(GUID更可靠) string nonce = Guid.NewGuid().ToString("N"); // 按字典序存储OAuth参数 var oauthParams = new SortedDictionary<string, string> { { "oauth_consumer_key", conKey }, { "oauth_nonce", nonce }, { "oauth_signature_method", "HMAC-SHA1" }, { "oauth_timestamp", timestampStr }, { "oauth_version", "1.0" } }; // 拼接参数为key=value&key=value格式 string paramString = string.Join("&", oauthParams.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}")); // 构建签名基字符串 string signatureBaseString = $"GET&{Uri.EscapeDataString(requestUrl)}&{Uri.EscapeDataString(paramString)}"; // 生成HMAC-SHA1签名 string signature = GetSha1Hash($"{conSecret}&", signatureBaseString); // 构建符合格式的Authorization头 string authHeader = string.Join(", ", oauthParams.Select(kv => $"{kv.Key}=\"{Uri.EscapeDataString(kv.Value)}\"") .Append($"oauth_signature=\"{Uri.EscapeDataString(signature)}\"")); return authHeader; }
SHA1哈希生成方法(优化编码兼容性)
public static string GetSha1Hash(string key, string baseSignatureString) { var encoding = System.Text.Encoding.UTF8; // 兼容非ASCII字符 byte[] keyBytes = encoding.GetBytes(key); byte[] messageBytes = encoding.GetBytes(baseSignatureString); using (HMACSHA1 hmacSha1 = new HMACSHA1(keyBytes)) { byte[] hashedBytes = hmacSha1.ComputeHash(messageBytes); return Convert.ToBase64String(hashedBytes); } }
请求代码修正
// 确保URL与签名基字符串完全一致(去除末尾斜杠) string requestUrl = $"{websites.Url.TrimEnd('/')}/wp-json/wc/v3/products"; var oAuthSignature = Utility.GetoAuthToken(websites.CustomerKey, websites.CustomerSecret, requestUrl); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth", oAuthSignature); var response = await _client.GetAsync(requestUrl); var result = await response.Content.ReadAsStringAsync();
额外注意点
- Nonce需保证每次请求唯一,使用GUID比重复timestamp更可靠
- 签名生成后需进行URL转义,避免特殊字符破坏头格式
- 参数排序必须严格按字典序,这是OAuth 1.0签名验证的强制要求
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

