mirror of https://github.com/abpframework/abp.git
7 changed files with 149 additions and 1 deletions
@ -0,0 +1,17 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.Security.Claims; |
|||
|
|||
[Serializable] |
|||
public class AbpClaimCacheItem |
|||
{ |
|||
public string Type { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
|
|||
public AbpClaimCacheItem(string type, string value) |
|||
{ |
|||
Type = type; |
|||
Value = value; |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Security.Principal; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace Volo.Abp.Identity; |
|||
|
|||
public class IdentityDynamicClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency |
|||
{ |
|||
public virtual async Task ContributeAsync(AbpClaimsPrincipalContributorContext context) |
|||
{ |
|||
var identity = context.ClaimsPrincipal.Identities.FirstOrDefault(); |
|||
var userId = identity?.FindUserId(); |
|||
if (userId == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var cache = context.GetRequiredService<IdentityDynamicClaimsPrincipalContributorCache>(); |
|||
var dynamicClaims = await cache.GetAsync(userId.Value, identity.FindTenantId()); |
|||
foreach (var claim in dynamicClaims) |
|||
{ |
|||
identity.AddOrReplace(new Claim(claim.Type, claim.Value)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace Volo.Abp.Identity; |
|||
|
|||
public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependency |
|||
{ |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
|
|||
public IdentityDynamicClaimsPrincipalContributorCache(IServiceProvider serviceProvider) |
|||
{ |
|||
this.ServiceProvider = serviceProvider; |
|||
} |
|||
|
|||
public virtual async Task<List<AbpClaimCacheItem>> GetAsync(Guid userId, Guid? tenantId = null) |
|||
{ |
|||
var logger = ServiceProvider.GetRequiredService<ILogger<IdentityDynamicClaimsPrincipalContributorCache>>(); |
|||
logger.LogDebug($"Get dynamic claims cache for user: {userId}"); |
|||
|
|||
var cache = ServiceProvider.GetRequiredService<IDistributedCache<List<AbpClaimCacheItem>>>(); |
|||
|
|||
return await cache.GetOrAddAsync($"{nameof(IdentityDynamicClaimsPrincipalContributorCache)}_{tenantId}_{userId}", async () => |
|||
{ |
|||
using (ServiceProvider.GetRequiredService<ICurrentTenant>().Change(tenantId)) |
|||
{ |
|||
logger.LogDebug($"Filling dynamic claims cache for user: {userId}"); |
|||
var userManager = ServiceProvider.GetRequiredService<IdentityUserManager>(); |
|||
var user = await userManager.FindByIdAsync(userId.ToString()); |
|||
if (user == null) |
|||
{ |
|||
logger.LogWarning($"User not found: {userId}"); |
|||
return new List<AbpClaimCacheItem>(); |
|||
} |
|||
var factory = ServiceProvider.GetRequiredService<IUserClaimsPrincipalFactory<IdentityUser>>(); |
|||
var principal = await factory.CreateAsync(user); |
|||
var options = ServiceProvider.GetRequiredService<IOptions<AbpClaimsPrincipalFactoryOptions>>().Value; |
|||
return principal.Identities.FirstOrDefault()?.Claims.Where(c => options.DynamicClaims.Contains(c.Type)).Select(c => new AbpClaimCacheItem(c.Type, c.Value)).ToList(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public virtual async Task ClearAsync(Guid userId, Guid? tenantId = null) |
|||
{ |
|||
var cache = ServiceProvider.GetRequiredService<IDistributedCache<List<AbpClaimCacheItem>>>(); |
|||
var logger = ServiceProvider.GetRequiredService<ILogger<IdentityDynamicClaimsPrincipalContributorCache>>(); |
|||
logger.LogDebug($"Clearing dynamic claims cache for user: {userId}"); |
|||
await cache.RemoveAsync($"{nameof(IdentityDynamicClaimsPrincipalContributorCache)}_{tenantId}_{userId}"); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities.Events; |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace Volo.Abp.Identity; |
|||
|
|||
public class UserEntityUpdatedEventHandler : ILocalEventHandler<EntityUpdatedEventData<IdentityUser>>, ITransientDependency |
|||
{ |
|||
public ILogger<UserEntityUpdatedEventHandler> Logger { get; set; } |
|||
|
|||
private readonly IdentityDynamicClaimsPrincipalContributorCache _cache; |
|||
|
|||
public UserEntityUpdatedEventHandler(IdentityDynamicClaimsPrincipalContributorCache cache) |
|||
{ |
|||
_cache = cache; |
|||
Logger = NullLogger<UserEntityUpdatedEventHandler>.Instance; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
public virtual async Task HandleEventAsync(EntityUpdatedEventData<IdentityUser> eventData) |
|||
{ |
|||
var userId = eventData.Entity.Id; |
|||
Logger.LogDebug($"Clearing dynamic claims cache for user: {userId}"); |
|||
await _cache.ClearAsync(userId, eventData.Entity.TenantId); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue