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