6 changed files with 187 additions and 1 deletions
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> |
||||
|
<Version>3.0.0</Version> |
||||
|
<Authors>LINGYUN</Authors> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> |
||||
|
<OutputPath>D:\LocalNuget</OutputPath> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Caching" Version="3.0.0" /> |
||||
|
<PackageReference Include="Volo.Abp.IdentityModel" Version="3.0.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -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 |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<IdentityModelAuthenticationCacheItem> Cache { get; } |
||||
|
public IdentityModelCachedAuthenticationService( |
||||
|
IOptions<AbpIdentityClientOptions> options, |
||||
|
ICancellationTokenProvider cancellationTokenProvider, |
||||
|
IHttpClientFactory httpClientFactory, |
||||
|
ICurrentTenant currentTenant, |
||||
|
IStringEncryptionService encryptionService, |
||||
|
IDistributedCache<IdentityModelAuthenticationCacheItem> cache, |
||||
|
IOptions<IdentityModelHttpRequestMessageOptions> identityModelHttpRequestMessageOptions) |
||||
|
: base(options, cancellationTokenProvider, httpClientFactory, currentTenant, identityModelHttpRequestMessageOptions) |
||||
|
{ |
||||
|
Cache = cache; |
||||
|
EncryptionService = encryptionService; |
||||
|
} |
||||
|
|
||||
|
public override async Task<string> GetAccessTokenAsync(IdentityClientConfiguration configuration) |
||||
|
{ |
||||
|
var accessTokenCacheItem = await GetCacheItemAsync(configuration); |
||||
|
// 需要解密
|
||||
|
return EncryptionService.Decrypt(accessTokenCacheItem.AccessToken); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<IdentityModelAuthenticationCacheItem> 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<TokenResponse> 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[] { "<eof/>" }, StringSplitOptions.RemoveEmptyEntries); |
||||
|
throw new AbpException(withoutInnerException[0]); |
||||
|
} |
||||
|
|
||||
|
return tokenResponse; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
|
} |
||||
|
``` |
||||
Loading…
Reference in new issue