diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN.Abp.BlobStoring.Qiniu.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN.Abp.BlobStoring.Qiniu.csproj
index ebcd78730..6357ced54 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN.Abp.BlobStoring.Qiniu.csproj
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN.Abp.BlobStoring.Qiniu.csproj
@@ -5,7 +5,7 @@
true
3.0.0
LINGYUN
- 阿里云Oss对象存储Abp集成
+ 七牛云Oss对象存储Abp集成
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN.Abp.IdentityModel.csproj b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN.Abp.IdentityModel.csproj
new file mode 100644
index 000000000..7236bdba8
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN.Abp.IdentityModel.csproj
@@ -0,0 +1,20 @@
+
+
+
+ netstandard2.0
+
+ true
+ 3.0.0
+ LINGYUN
+
+
+
+ D:\LocalNuget
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/AbpCachedIdentityModelModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/AbpCachedIdentityModelModule.cs
new file mode 100644
index 000000000..9c5dd44b3
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/AbpCachedIdentityModelModule.cs
@@ -0,0 +1,13 @@
+using Volo.Abp.IdentityModel;
+using Volo.Abp.Modularity;
+using Volo.Abp.Security;
+
+namespace LINGYUN.Abp.IdentityModel
+{
+ [DependsOn(
+ typeof(AbpIdentityModelModule),
+ typeof(AbpSecurityModule))]
+ public class AbpCachedIdentityModelModule : AbpModule
+ {
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/IdentityModelAuthenticationCacheItem.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/IdentityModelAuthenticationCacheItem.cs
new file mode 100644
index 000000000..f9a4c6759
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/IdentityModelAuthenticationCacheItem.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace LINGYUN.Abp.IdentityModel
+{
+ public class IdentityModelAuthenticationCacheItem
+ {
+ public string AccessToken { get; set; }
+ public IdentityModelAuthenticationCacheItem()
+ {
+
+ }
+
+ public IdentityModelAuthenticationCacheItem(string accessToken)
+ {
+ AccessToken = accessToken;
+ }
+
+ public static string CalculateCacheKey(string grantType, string clientId, string userName = null)
+ {
+ if (userName.IsNullOrWhiteSpace())
+ {
+ return "gt:" + grantType + ",ci:" + clientId;
+ }
+ return "gt:" + grantType + ",ci:" + clientId + ",un:" + userName;
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/IdentityModelCachedAuthenticationService.cs b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/IdentityModelCachedAuthenticationService.cs
new file mode 100644
index 000000000..864168ed0
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/LINGYUN/Abp/IdentityModel/IdentityModelCachedAuthenticationService.cs
@@ -0,0 +1,107 @@
+using IdentityModel.Client;
+using Microsoft.Extensions.Caching.Distributed;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.Caching;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.IdentityModel;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Security.Encryption;
+using Volo.Abp.Threading;
+
+namespace LINGYUN.Abp.IdentityModel
+{
+ [Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
+ [ExposeServices(
+ typeof(IIdentityModelAuthenticationService),
+ typeof(IdentityModelAuthenticationService))]
+ public class IdentityModelCachedAuthenticationService : IdentityModelAuthenticationService
+ {
+ protected IStringEncryptionService EncryptionService { get; }
+ protected IDistributedCache Cache { get; }
+ public IdentityModelCachedAuthenticationService(
+ IOptions options,
+ ICancellationTokenProvider cancellationTokenProvider,
+ IHttpClientFactory httpClientFactory,
+ ICurrentTenant currentTenant,
+ IStringEncryptionService encryptionService,
+ IDistributedCache cache,
+ IOptions identityModelHttpRequestMessageOptions)
+ : base(options, cancellationTokenProvider, httpClientFactory, currentTenant, identityModelHttpRequestMessageOptions)
+ {
+ Cache = cache;
+ EncryptionService = encryptionService;
+ }
+
+ public override async Task GetAccessTokenAsync(IdentityClientConfiguration configuration)
+ {
+ var accessTokenCacheItem = await GetCacheItemAsync(configuration);
+ // 需要解密
+ return EncryptionService.Decrypt(accessTokenCacheItem.AccessToken);
+ }
+
+ protected virtual async Task GetCacheItemAsync(IdentityClientConfiguration configuration)
+ {
+ var cacheKey = IdentityModelAuthenticationCacheItem.CalculateCacheKey(configuration.GrantType, configuration.ClientId, configuration.UserName);
+
+ Logger.LogDebug($"IdentityModelCachedAuthenticationService.GetCacheItemAsync: {cacheKey}");
+
+ var cacheItem = await Cache.GetAsync(cacheKey);
+
+ if (cacheItem != null)
+ {
+ Logger.LogDebug($"Found in the cache: {cacheKey}");
+ return cacheItem;
+ }
+
+ Logger.LogDebug($"Not found in the cache: {cacheKey}");
+
+ var tokenResponse = await GetAccessTokenResponseAsync(configuration);
+ // 需要加密
+ var accessToken = EncryptionService.Encrypt(tokenResponse.AccessToken);
+ cacheItem = new IdentityModelAuthenticationCacheItem(accessToken);
+ var cacheEntryOptions = new DistributedCacheEntryOptions
+ {
+ // 缓存前两分钟过期
+ AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(tokenResponse.ExpiresIn - 120)
+ };
+
+ Logger.LogDebug($"Setting the cache item: {cacheKey}");
+ await Cache.SetAsync(cacheKey, cacheItem, cacheEntryOptions);
+
+ Logger.LogDebug($"Finished setting the cache item: {cacheKey}");
+
+ return cacheItem;
+ }
+
+ protected virtual async Task GetAccessTokenResponseAsync(IdentityClientConfiguration configuration)
+ {
+ var discoveryResponse = await GetDiscoveryResponse(configuration);
+ if (discoveryResponse.IsError)
+ {
+ 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)
+ {
+ 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]);
+ }
+
+ return tokenResponse;
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/README.md b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/README.md
new file mode 100644
index 000000000..54b9056d7
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.IdentityModel/README.md
@@ -0,0 +1,19 @@
+# LINGYUN.Abp.IdentityModel
+
+abp框架 **IIdentityModelAuthenticationService**接口缓存版本
+
+因官方**Volo.Abp.IdentityModel**模块没有对接口授权缓存,每次内部调用都会请求IDS服务器,会加重IDS服务器压力,
+创建使用缓存的接口实现
+
+## 配置使用
+
+模块按需引用,需要配置**Volo.Abp.IdentityModel**模块所需配置项
+
+
+```csharp
+[DependsOn(typeof(AbpCachedIdentityModelModule))]
+public class YouProjectModule : AbpModule
+{
+ // other
+}
+```
\ No newline at end of file