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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:35:33