[英]How to consume ASP.NET Web API 2.0 with bearer token via a desktop/console application
我有一个使用 ASP.NET Web API 的控制台/winform(非浏览器)应用程序。 我已经实现了基于令牌的身份验证来保护我的 web api,并且需要找出检索令牌的最佳位置,因为我已经使用HttpClientHelper
类遵循存储库模式?
获取令牌:
private static string GetToken(string url, string userName, string password)
{
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>( "grant_type", "password" ),
new KeyValuePair<string, string>( "username", userName ),
new KeyValuePair<string, string> ( "Password", password )
};
var content = new FormUrlEncodedContent(pairs);
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using(var client = new HttpClient())
{
var response = client.PostAsync(url + "Token", content).Result;
return response.Content.ReadAsStringAsync().Result;
}
}
HttpClient 帮助程序:
public sealed class HttpClientHelper<T, TResourceIdentifier> : IDisposable where T : class
{
#region Constructors
public HttpClientHelper(string serviceBaseAddress, string addressSuffix, string token)
{
_serviceBaseAddress = serviceBaseAddress;
_addressSuffix = addressSuffix;
_token = token
_httpClient = MakeHttpClient();
}
#endregion
#region CRUD
public async Task<IEnumerable<T>> GetManyAsync()
{
var responseMessage = await _httpClient.GetAsync(_addressSuffix);
if (responseMessage.IsSuccessStatusCode)
return await responseMessage.Content.ReadAsAsync<IEnumerable<T>>();
return null;
}
// Other CRUD operations
#endregion
#region Private Methods
private HttpClient MakeHttpClient()
{
_httpClient = new HttpClient
{
BaseAddress = new Uri(_serviceBaseAddress),
MaxResponseContentBufferSize = int.MaxValue,
DefaultRequestHeaders = {Authorization = new AuthenticationHeaderValue("bearer", token)}
};
// Other settings
return _httpClient;
}
#region IDisposable Members
private void Dispose(bool disposing)
{
if (_disposed || !disposing) return;
if (_httpClient != null)
{
var hc = _httpClient;
_httpClient = null;
hc.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~HttpClientHelper()
{
Dispose(false);
}
#endregion IDisposable Members
}
}
我的通用类:
internal class GenericRepository<T, TResourceIdentifier> : IDisposable, IGenericRepository<T, TResourceIdentifier> where T : class
{
private bool _disposed;
protected HttpClientHelper<T, TResourceIdentifier> Client;
protected GenericRepository(string serviceBaseAddress, string addressSuffix, string token)
{
Client = new HttpClientHelper<T, TResourceIdentifier>(serviceBaseAddress, addressSuffix, token);
}
public async Task<IEnumerable<T>> GetManyAsync()
{
return await Client.GetManyAsync();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (_disposed || !disposing) return;
if (Client != null)
{
var mc = Client;
Client = null;
mc.Dispose();
}
_disposed = true;
}
}
自定义存储库类示例:
internal class CustomerRepository : GenericRepository<Customer, int> , ICustomerRepository
{
internal CustomerRepository() : base(Properties.Settings.Default.Url, "Customers/", ***TOKEN***)
{
}
}
用法:
private readonly ICustomerRepository _customerRepository = new CustomerRepository();
private async Task<Customer> GetCustomer(int customerId)
{
var customer = new Customer();
try
{
customer = await _customerRepository.GetAsync(customerId);
}
catch (Exception ex)
{
// Log the error
}
return customer;
}
在声明我的 IRepository 时,我究竟在哪里获取/分配令牌而不会出现 nullexception 错误?
在任何情况下,您都不应该每次都实例化一个新的HttpClient
。 IDisposable
可能会让你认为你应该这样做,但它是一种反模式。 检查https://softwareengineering.stackexchange.com/questions/330364/should-we-create-a-new-single-instance-of-httpclient-for-all-requests以获取有关此事的大量资源。
与令牌相同的事情。 只要您的令牌处于活动状态,就可以使用它。 使用安全问题应由身份提供者和超时解决。 这就是为什么有一个刷新令牌来处理令牌过期的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.