mirror of https://github.com/abpframework/abp
parent
7fde5e3dd1
commit
44ef56c2d8
@ -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