带有普通查询字符串的 HttpClient GET 请求(连同 oAuth1.0)
Posted
技术标签:
【中文标题】带有普通查询字符串的 HttpClient GET 请求(连同 oAuth1.0)【英文标题】:HttpClient GET request with plain querystring (together with oAuth1.0) 【发布时间】:2021-12-07 09:09:12 【问题描述】:我正在尝试做一个简单的请求,但我无法让它工作。 我认为这与单个参数有关。
示例代码:
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);
token.RequestUrl = $"uri.Scheme://uri.Hosturi.AbsolutePath";
var 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;
我确实需要 oAuth1 的授权码,当我尝试在没有 eq(id,8c17b598-67e4-4b9b-8d18-ab0918ed82d9)
的情况下执行此操作时它可以工作,但添加它时它会停止工作。现在不确定这是否与 oAuth1 或是否与常规请求有关。
但我确实记得过去使用非键值查询参数存在一些问题。你们有什么想法吗?
【问题讨论】:
【参考方案1】:我注意到这是由我使用的 oAuth1 实现引起的。我查看了几个示例,例如 twitter,并创建了我自己的版本,并将结果与 Postman 生成的结果进行了比较,而 twitter 在他们的示例中显示: https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature#f2
我现在使用的代码:
/// <summary>
/// OAuth 1.0 signing
/// </summary>
public class OAuth1
#region CONSTRUCTORS
/// <summary>
/// Default constructor
/// </summary>
public OAuth1()
this.Timestamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
this.Nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(this.Timestamp + this.Timestamp + this.Timestamp));
this.SignatureMethod = "HMAC-SHA1";
this.Version = "1.0";
this.Data = new Dictionary<string, string>();
#endregion
#region METHODS_PUBLIC
/// <summary>
/// Get authorization header
/// </summary>
/// <returns></returns>
public string GetAuthorizationHeader()
var properties = this.GetOAuthProperties();
properties.Add("oauth_signature", Uri.EscapeDataString(this.GetSignature()));
return "OAuth " + string.Join(",", properties.Select(q => $"q.Key=\"q.Value\""));
/// <summary>
/// Get signature only
/// </summary>
/// <returns></returns>
public string GetSignature()
var uriBuilder = new UriBuilder(this.RequestUri);
uriBuilder.Query = "";
var signValues = new List<string>();
signValues.Add(this.RequestMethod.ToString().ToUpperInvariant());
signValues.Add(uriBuilder.Uri.AbsoluteUri);
signValues.Add(string.Join("&", this.GetSigningProperties().Select(q => $"q.Key=q.Value")));
var signKey = $"this.ConsumerSecret&this.TokenSecret";
var signMessage = string.Join("&", signValues.Select(q => Uri.EscapeDataString(q)));
return this.GetSha1Hash(signKey, signMessage);
#endregion
#region METHODS_PRIVATE
/// <summary>
/// Get properties which should be part of the signing process
/// </summary>
/// <returns></returns>
private SortedDictionary<string,string> GetSigningProperties()
var result = this.GetOAuthProperties();
var arguments = HttpUtility.ParseQueryString(this.RequestUri.Query);
for (var i = 0; i < arguments.Count; i++)
var key = arguments.Keys[i];
var value = arguments.GetValues(i)[0];
if (string.IsNullOrEmpty(key))
key = value;
value = null;
result.Add(Uri.EscapeDataString(key ?? ""), Uri.EscapeDataString(value ?? ""));
foreach(var dataArg in this.Data)
result.Add(Uri.EscapeDataString(dataArg.Key), Uri.EscapeDataString(dataArg.Value));
return result;
/// <summary>
/// Get SHA1 Hash
/// </summary>
/// <param name="key"></param>
/// <param name="message"></param>
/// <returns></returns>
private string GetSha1Hash(string key, string message)
var encoding = new ASCIIEncoding();
byte[] keyBytes = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(message);
string strSignature = string.Empty;
using (var SHA1 = new HMACSHA1(keyBytes))
var Hashed = SHA1.ComputeHash(messageBytes);
strSignature = Convert.ToBase64String(Hashed);
return strSignature;
/// <summary>
/// Get OAuth properties only (used for signing and header)
/// </summary>
/// <returns></returns>
private SortedDictionary<string, string> GetOAuthProperties()
var result = new SortedDictionary<string, string>();
result.Add(Uri.EscapeDataString("oauth_consumer_key"), Uri.EscapeDataString(this.ConsumerKey));
result.Add(Uri.EscapeDataString("oauth_nonce"), Uri.EscapeDataString(this.Nonce));
result.Add(Uri.EscapeDataString("oauth_signature_method"), Uri.EscapeDataString(this.SignatureMethod));
result.Add(Uri.EscapeDataString("oauth_timestamp"), Uri.EscapeDataString(this.Timestamp));
if (!string.IsNullOrEmpty(this.Token))
result.Add(Uri.EscapeDataString("oauth_token"), Uri.EscapeDataString(this.Token));
result.Add(Uri.EscapeDataString("oauth_version"), Uri.EscapeDataString(this.Version));
return result;
#endregion
#region PROPERTIES
/// <summary>
/// Request method
/// </summary>
public Models.Thpr.Common.Enums.ERequestMethod RequestMethod get; set;
/// <summary>
/// Request URI
/// </summary>
public Uri RequestUri get; set;
/// <summary>
/// Timestamp
/// </summary>
public string Timestamp get; set;
/// <summary>
/// Nonce
/// </summary>
public string Nonce get; set;
/// <summary>
/// Consumer key
/// </summary>
public string ConsumerKey get; set;
/// <summary>
/// Consumer secret
/// </summary>
public string ConsumerSecret get; set;
/// <summary>
/// Signature Method
/// </summary>
public string SignatureMethod get; set;
/// <summary>
/// Token
/// </summary>
public string Token get; set;
/// <summary>
/// Token secret
/// </summary>
public string TokenSecret get; set;
/// <summary>
/// Version
/// </summary>
public string Version get; set;
/// <summary>
/// Data arguments
/// </summary>
public Dictionary<string, string> Data get; set;
#endregion
【讨论】:
以上是关于带有普通查询字符串的 HttpClient GET 请求(连同 oAuth1.0)的主要内容,如果未能解决你的问题,请参考以下文章
HttpClient使用详解与实战一:普通的GET和POST请求
带有 .Get() 对 Azure 搜索 API 的请求的 Angular HttpClient“未知错误”
带有“@”的 HttpClient 访问 url(在符号处)