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