Rest客户端的回答非常完美!(我点赞了它)
但是,万一你想要“原始”的方式
..........
我使用HttpClient让它工作了。
“抽象地”说,你正在做以下事情:
- 创建一个POST请求。
- 使用有效载荷“类型”为'x-www-form-urlencoded'的主体。(请参见FormUrlEncodedContent https://learn.microsoft.com/en-us/dotnet/api/system.net.http.formurlencodedcontent?view=net-5.0 并注意构造函数:https://learn.microsoft.com/en-us/dotnet/api/system.net.http.formurlencodedcontent.-ctor?view=net-5.0)
- 在有效载荷“类型”:x-www-form-urlencoded中,您将放入某些值,如grant_type、client_id、client_secret等。
顺便说一句,尝试在PostMan中让它工作,然后使用下面的代码更容易“编码”。
但是,我们来看看使用HttpClient的代码。
顺带提一下,newtonsoft 的引用是为了“弥合”C#命名规范和json元素名称之间的差距。 (下面是部分代码示例)。C#属性应该是PascalCase,而json元素名称(在本例中)是“snake-case”。
[JsonProperty("access_token")]
public string AccessToken { get; set; }
如果您使用的是 .NET Core 5.0 或更高版本,则可以使用 System.Text.Json。
但现在我们来谈谈:
.......
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
private static async Task<Token> GetElibilityToken(HttpClient client)
{
string baseAddress = @"https://blah.blah.blah.com/oauth2/token";
string grant_type = "client_credentials";
string client_id = "myId";
string client_secret = "shhhhhhhhhhhhhhItsSecret";
var form = new Dictionary<string, string>
{
{"grant_type", grant_type},
{"client_id", client_id},
{"client_secret", client_secret},
};
HttpResponseMessage tokenResponse = await client.PostAsync(baseAddress, new FormUrlEncodedContent(form));
var jsonContent = await tokenResponse.Content.ReadAsStringAsync();
Token tok = JsonConvert.DeserializeObject<Token>(jsonContent);
return tok;
}
internal class Token
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
这里是另一个工作示例(基于上面的答案)......稍微进行了一些调整。有时令牌服务会出现问题:
private static async Task<Token> GetATokenToTestMyRestApiUsingHttpClient(HttpClient client)
{
OAuthValues oav = GetOAuthValues();
var form = new Dictionary<string, string>
{
{ "grant_type", oav.GrantType },
{ "client_id", oav.ClientId },
{ "client_secret", oav.ClientSecret }
};
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("cache-control", "no-cache");
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, oav.TokenUrl);
req.Content = new FormUrlEncodedContent(form);
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
HttpResponseMessage tokenResponse = await client.SendAsync(req);
Console.WriteLine(string.Format("HttpResponseMessage.ReasonPhrase='{0}'", tokenResponse.ReasonPhrase));
if (!tokenResponse.IsSuccessStatusCode)
{
throw new HttpRequestException("Call to get Token with HttpClient failed.");
}
var jsonContent = await tokenResponse.Content.ReadAsStringAsync();
Token tok = JsonConvert.DeserializeObject<Token>(jsonContent);
return tok;
}
附加
额外资料!
如果您遇到
"根据验证程序,远程证书无效。"
异常......您可以添加一个处理程序来查看发生了什么(如有必要进行调整)
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
using System.Net;
namespace MyNamespace
{
public class MyTokenRetrieverWithExtraStuff
{
public static async Task<Token> GetElibilityToken()
{
using (HttpClientHandler httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationCallBack;
using (HttpClient client = new HttpClient(httpClientHandler))
{
return await GetElibilityToken(client);
}
}
}
private static async Task<Token> GetElibilityToken(HttpClient client)
{
string baseAddress = @"https://blah.blah.blah.com/oauth2/token";
string grant_type = "client_credentials";
string client_id = "myId";
string client_secret = "shhhhhhhhhhhhhhItsSecret";
var form = new Dictionary<string, string>
{
{"grant_type", grant_type},
{"client_id", client_id},
{"client_secret", client_secret},
};
HttpResponseMessage tokenResponse = await client.PostAsync(baseAddress, new FormUrlEncodedContent(form));
var jsonContent = await tokenResponse.Content.ReadAsStringAsync();
Token tok = JsonConvert.DeserializeObject<Token>(jsonContent);
return tok;
}
private static bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
if (chain != null && chain.ChainStatus != null)
{
foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
{
if ((certificate.Subject == certificate.Issuer) &&
(status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
{
continue;
}
else
{
if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
{
return false;
}
}
}
}
return true;
}
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch) != 0)
{
if (certificate.Subject.Contains("localhost"))
{
HttpRequestMessage castSender = sender as HttpRequestMessage;
if (null != castSender)
{
if (castSender.RequestUri.Host.Contains("127.0.0.1"))
{
return true;
}
}
}
}
return false;
}
public class Token
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
}
}
........................
我最近发现(2020年1月)一篇关于这方面的文章。 我会在这里添加一个链接....有时候让两个不同的人展示/解释它可以帮助正在尝试学习它的人。
http://luisquintanilla.me/2017/12/25/client-credentials-authentication-csharp/