From a1ca5979f87d725a820f97f2a6b2dd76f440ad31 Mon Sep 17 00:00:00 2001
From: maliming <6908465+maliming@users.noreply.github.com>
Date: Mon, 13 Jul 2020 17:57:35 +0800
Subject: [PATCH] Cache the AccessToken in IdentityModelAuthenticationService.
Resolve #4603
---
.../Volo.Abp.IdentityModel.csproj | 1 +
.../IdentityModel/AbpIdentityModelModule.cs | 4 +-
.../IdentityModelAuthenticationService.cs | 45 ++++++++++++++-----
.../IdentityModelTokenCacheItem.cs | 29 ++++++++++++
4 files changed, 68 insertions(+), 11 deletions(-)
create mode 100644 framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelTokenCacheItem.cs
diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj
index 0143db8265..1fb77b36d9 100644
--- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj
+++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj
@@ -17,6 +17,7 @@
+
diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs
index 7ab97c49fe..bf499e7b5f 100644
--- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs
+++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/AbpIdentityModelModule.cs
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Caching;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
@@ -7,7 +8,8 @@ namespace Volo.Abp.IdentityModel
{
[DependsOn(
typeof(AbpThreadingModule),
- typeof(AbpMultiTenancyModule)
+ typeof(AbpMultiTenancyModule),
+ typeof(AbpCachingModule)
)]
public class AbpIdentityModelModule : AbpModule
{
diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
index 5e8c67a9ab..c20d473f81 100644
--- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
+++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
@@ -10,6 +10,8 @@ using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
+using Microsoft.Extensions.Caching.Distributed;
+using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
@@ -26,18 +28,21 @@ namespace Volo.Abp.IdentityModel
protected IHttpClientFactory HttpClientFactory { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IdentityModelHttpRequestMessageOptions IdentityModelHttpRequestMessageOptions { get; }
+ protected IDistributedCache Cache { get; }
public IdentityModelAuthenticationService(
IOptions options,
ICancellationTokenProvider cancellationTokenProvider,
IHttpClientFactory httpClientFactory,
ICurrentTenant currentTenant,
- IOptions identityModelHttpRequestMessageOptions)
+ IOptions identityModelHttpRequestMessageOptions,
+ IDistributedCache cache)
{
ClientOptions = options.Value;
CancellationTokenProvider = cancellationTokenProvider;
HttpClientFactory = httpClientFactory;
CurrentTenant = currentTenant;
+ Cache = cache;
IdentityModelHttpRequestMessageOptions = identityModelHttpRequestMessageOptions.Value;
Logger = NullLogger.Instance;
}
@@ -76,21 +81,36 @@ namespace Volo.Abp.IdentityModel
throw new AbpException($"Could not retrieve the OpenId Connect discovery document! ErrorType: {discoveryResponse.ErrorType}. Error: {discoveryResponse.Error}");
}
- var tokenResponse = await GetTokenResponse(discoveryResponse, configuration);
-
- if (tokenResponse.IsError)
+ var cacheKey = CalculateCacheKey(discoveryResponse, configuration);
+ var tokenCacheItem = await Cache.GetAsync(cacheKey);
+ if (tokenCacheItem == null)
{
- if (tokenResponse.ErrorDescription != null)
+ var tokenResponse = await GetTokenResponse(discoveryResponse, configuration);
+
+ if (tokenResponse.IsError)
{
- throw new AbpException($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}");
+ if (tokenResponse.ErrorDescription != null)
+ {
+ throw new AbpException($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. " +
+ $"Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}");
+ }
+
+ var rawError = tokenResponse.Raw;
+ var withoutInnerException = rawError.Split(new string[] { "" }, StringSplitOptions.RemoveEmptyEntries);
+ throw new AbpException(withoutInnerException[0]);
}
- var rawError = tokenResponse.Raw;
- var withoutInnerException = rawError.Split(new string[] { "" }, StringSplitOptions.RemoveEmptyEntries);
- throw new AbpException(withoutInnerException[0]);
+ await Cache.SetAsync(cacheKey, new IdentityModelTokenCacheItem(tokenResponse.AccessToken),
+ new DistributedCacheEntryOptions()
+ {
+ //Subtract 10 seconds of network request time.
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(tokenResponse.ExpiresIn - 10)
+ });
+
+ return tokenResponse.AccessToken;
}
- return tokenResponse.AccessToken;
+ return tokenCacheItem.AccessToken;
}
protected virtual void SetAccessToken(HttpClient client, string accessToken)
@@ -209,5 +229,10 @@ namespace Volo.Abp.IdentityModel
client.DefaultRequestHeaders.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString());
}
}
+
+ protected virtual string CalculateCacheKey(DiscoveryDocumentResponse discoveryResponse, IdentityClientConfiguration configuration)
+ {
+ return IdentityModelTokenCacheItem.CalculateCacheKey(discoveryResponse, configuration);
+ }
}
}
diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelTokenCacheItem.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelTokenCacheItem.cs
new file mode 100644
index 0000000000..8d01b83c32
--- /dev/null
+++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelTokenCacheItem.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Linq;
+using IdentityModel.Client;
+using Volo.Abp.MultiTenancy;
+
+namespace Volo.Abp.IdentityModel
+{
+ [Serializable]
+ [IgnoreMultiTenancy]
+ public class IdentityModelTokenCacheItem
+ {
+ public string AccessToken { get; set; }
+
+ public IdentityModelTokenCacheItem()
+ {
+
+ }
+
+ public IdentityModelTokenCacheItem(string accessToken)
+ {
+ AccessToken = accessToken;
+ }
+
+ public static string CalculateCacheKey(DiscoveryDocumentResponse discoveryResponse, IdentityClientConfiguration configuration)
+ {
+ return discoveryResponse.TokenEndpoint + string.Join(",", configuration.Select(x => x.Key + ":" + x.Value));
+ }
+ }
+}