我有这种情况:与Web Api 2连接的Xamarin.Forms应用程序。我发出所有请求并获取所需的数据。现在,当会话令牌过期时,我需要刷新令牌,但不注销用户。用户不需要知道何时刷新令牌。如何组织它,在我发送请求时添加每个请求if语句,并检查令牌是否过期。这是我的要求之一:
public async Task<User> GetProfileSetup()
{
try
{
if (CrossConnectivity.Current.IsConnected)
{
string token = DependencyService.Get<ISharedFunctions>().GetAccessToken();
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
var response = await client.GetAsync(@"api/Profile/GetProfilSetup");
if (response.IsSuccessStatusCode)
{
string jsonMessage;
using (Stream responseStream = await response.Content.ReadAsStreamAsync())
{
jsonMessage = new StreamReader(responseStream).ReadToEnd();
}
User user = JsonConvert.DeserializeObject<User>(jsonMessage);
return user;
}
else
{
var m = response.Content.ToString();
return null;
}
}
else
{
return null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
string error = ex.Message;
return null;
}
}
P.S我的Api中有用于GetToken和RefreshToken的方法,它们正在起作用,只是如何组织刷新?
这实际上取决于您在项目中使用的是什么库。但是,假设您正在使用普通的c#来处理HTTP调用。
[OPTION 1] Polly
我可以推荐您查看Polly
这是一个很棒的图书馆,具有很多功能。您可以使用Retry
策略来处理过期的令牌:
var _unauthorizedPolicy = Policy
.Handle<Exception>(ex => ex.StatusCode == HttpStatusCode.Unauthorized) // check here for your exception to be the right one
.RetryAsync(3, async (exception, retryCount, context) =>
{
try
{
var token = await _authService.RefreshToken();
// save the new token or whatever you need to store it
}
catch (Exception ex)
{
// RefreshToken failed, you should probably sign out the user
SignOut();
}
});
这是Polly将尝试执行您的常规HTTP调用,并且如果失败并且在Handle
中指定了原因,则将触发重试机制,该机制将尝试刷新令牌,然后重试您的请求。最后,万一令牌无法刷新,您可以注销用户。当然,所有这些都可以自定义,请检查Polly的文档是否写得很好。
[请注意,您必须在Handle<T>
内放置正确的例外。我只是使用Exception
作为占位符,因为我不确定在您的情况下会抛出什么异常。
然后您将使用此策略调用方法:
var result = await _unauthorizedPolicy.ExecuteAsync(() => GetProfileSetup())
并且您可以将该策略重用于任何呼叫,而无需每次都创建它。
[OPTION 2] DelegatingHandler
我在这里想要另一个StackOverflow答案:How to Refresh a token using IHttpClientFactory
基本上,您可以拦截通过HttpClient进行的每个HTTP调用,并刷新/向请求添加令牌。
请注意,答案并不强制您使用IHttpClientFactory
,它也适用于简单的HttpClient
。
也有点偏离主题。您可能需要查找库来处理诸如修图之类的htt调用。它将真正减少样板代码的数量。