.NET Core 6.0 REST API调用OAuth 1.0接口始终返回无效签名
OAuth 1.0签名无效导致401错误的修复方案
问题核心
你在.NET Core 6.0中调用第三方OAuth 1.0 API时,因签名生成逻辑不符合规范,导致接口返回401状态码并提示"无效签名"。以下是代码中的关键错误及修正方案:
代码中的错误点
- 签名基串构造不规范:
OAuth 1.0要求签名基串必须遵循[HTTP方法]&[编码后的基础URL]&[编码后的排序参数串]格式,你的代码缺少HTTP方法、未对参数按字典序排序,且直接拼接URL与参数的方式错误。 - 签名密钥重复编码:
你已对ConsumerSecret和TokenSecret做了URL编码,生成signatureKey后再次编码,导致密钥值错误。 - URL处理不当:
直接将URL转小写可能不符合第三方服务要求,且未剥离URL中的查询参数(若存在)。
修正后的代码
using System.Security.Cryptography; using System.Text; using System.Net.Http; // 1. 生成UTC时间戳与随机Nonce var timeStamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString(); var nonce = Guid.NewGuid().ToString("N"); // 用GUID生成更可靠的唯一随机值 // 2. 按字典序存储OAuth参数(必须排序) var oauthParams = new SortedDictionary<string, string> { { "oauth_consumer_key", _tradeShiftConfigurations.ConsumerKey }, { "oauth_token", _tradeShiftConfigurations.Token }, { "oauth_signature_method", "HMAC-SHA1" }, { "oauth_timestamp", timeStamp }, { "oauth_nonce", nonce }, { "oauth_version", "1.0" } }; // 3. 提取基础URL(剥离查询参数) var uri = new Uri(url); var baseUrl = $"{uri.Scheme}://{uri.Host}{uri.AbsolutePath}"; // 4. 构造编码后的参数串 var paramString = string.Join("&", oauthParams.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}")); // 5. 生成符合规范的签名基串 var httpMethod = HttpMethod.Get.Method.ToUpper(); // 替换为实际请求方法(POST/PUT等) var signatureBase = $"{httpMethod}&{Uri.EscapeDataString(baseUrl)}&{Uri.EscapeDataString(paramString)}"; // 6. 生成签名密钥(无需重复编码) var signatureKey = $"{Uri.EscapeDataString(_tradeShiftConfigurations.ConsumerSecret)}&{Uri.EscapeDataString(_tradeShiftConfigurations.TokenSecret)}"; // 7. 计算HMAC-SHA1签名 using var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(signatureKey)); var signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(signatureBase)); var signature = Convert.ToBase64String(signatureBytes); // 8. 编码签名用于请求头 var encodedSignature = Uri.EscapeDataString(signature);
额外注意事项
- 确保HTTP方法与实际请求一致(如POST请求需替换
HttpMethod.Get为HttpMethod.Post)。 - 若请求包含其他查询参数或表单参数,必须将其加入
SortedDictionary中,与OAuth参数一起参与签名计算。 - 时间戳必须使用UTC时间,避免时区差异导致验证失败。
- Nonce只需保证同一时间戳下唯一,使用GUID是稳定可靠的实现方式。
内容的提问来源于stack exchange,提问作者Naveen Negi
相关产品推荐
相关产品推荐

