带OAuth1.0与非键值对查询串的HttpClient GET请求失败问题
问题原因
你的问题核心出在OAuth1.0签名生成规则和HttpUtility.ParseQueryString对非键值对查询参数的处理不兼容两方面:
- OAuth1.0 签名规则要求:根据RFC5849规范,生成请求签名时必须把所有请求参数(包括查询参数、表单参数、OAuth基础参数)统一编码后按字典序排序拼接,任何参数遗漏都会导致最终签名和服务端验签结果不一致,直接校验失败。
- 非键值对参数解析异常:
HttpUtility.ParseQueryString处理?eq(id,8c17b598-67e4-4b9b-8d18-ab0918ed82d9)这种不带=的查询串时,会将整个eq(id,xxx)识别为键,对应值设为null,绝大多数OAuth1.0库生成签名时会自动忽略值为null的参数,导致签名计算时没把这个查询参数纳入,但是实际请求又携带了该参数,最终出现验签失败。
解决方法
调整参数解析逻辑,避免HttpUtility.ParseQueryString生成null值导致参数丢失,修改后的核心代码如下:
var uri = new Uri("http://www.mydomain.nl/?eq(id,8c17b598-67e4-4b9b-8d18-ab0918ed82d9)"); var consumerKey = "[mykey]"; var consumerSecret = "[mysecret]"; var token = OAuthRequest.ForRequestToken(consumerKey, consumerSecret); // 基地址统一不带查询参数,符合绝大多数OAuth库的入参要求 token.RequestUrl = $"{uri.Scheme}://{uri.Host}{uri.AbsolutePath}"; var arguments = new NameValueCollection(); var rawQuery = uri.Query.TrimStart('?'); if (!string.IsNullOrEmpty(rawQuery)) { // 非键值对参数手动处理,值设为空字符串避免被库丢弃 if (!rawQuery.Contains('=')) { arguments.Add(rawQuery, ""); } else { // 原有键值对参数走标准解析逻辑 arguments = HttpUtility.ParseQueryString(uri.Query); } } var header = token.GetAuthorizationHeader(arguments); using (var httpClient = new HttpClient()) { var request = new HttpRequestMessage(); request.RequestUri = uri; request.Headers.Add("Authorization", header); using (var response = await httpClient.SendAsync(request)) { var data = await response.Content.ReadAsStringAsync(); var x = 1; } }
校验技巧
如果修改后仍有问题,可以本地打印出生成签名的所有参数拼接后的原始字符串,和服务端验签时的参数拼接结果对比,即可快速定位是否是参数遗漏、编码规则不一致导致的签名错误。
内容的提问来源于stack exchange,提问作者Josjr87
相关产品推荐
相关产品推荐

