diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs index 8ed3cffd2e8..5791e05d8f7 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs @@ -1,11 +1,19 @@ -namespace Volo.Abp.AspNetCore.SignalR; +using System; + +namespace Volo.Abp.AspNetCore.SignalR; public class AbpSignalROptions { public HubConfigList Hubs { get; } + /// + /// Default: 5 seconds. + /// + public TimeSpan? CheckDynamicClaimsInterval { get; set; } + public AbpSignalROptions() { Hubs = new HubConfigList(); + CheckDynamicClaimsInterval = TimeSpan.FromSeconds(5); } } diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs index c7b8c029cf2..7f77992ce32 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp.Security.Claims; @@ -14,7 +16,7 @@ public class AbpAuthenticationHubFilter : IHubFilter { var currentPrincipalAccessor = invocationContext.ServiceProvider.GetRequiredService(); var claimsPrincipal = invocationContext.Context.User; - await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, invocationContext.ServiceProvider, invocationContext.Context); + await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, invocationContext.ServiceProvider, invocationContext.Context, false); using (currentPrincipalAccessor.Change(claimsPrincipal!)) { return await next(invocationContext); @@ -25,7 +27,7 @@ public virtual async Task OnConnectedAsync(HubLifetimeContext context, Func(); var claimsPrincipal = context.Context.User; - await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, context.ServiceProvider, context.Context); + await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, context.ServiceProvider, context.Context, true); using (currentPrincipalAccessor.Change(claimsPrincipal!)) { await next(context); @@ -36,24 +38,43 @@ public virtual async Task OnDisconnectedAsync(HubLifetimeContext context, Except { var currentPrincipalAccessor = context.ServiceProvider.GetRequiredService(); var claimsPrincipal = context.Context.User; - await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, context.ServiceProvider, context.Context); + await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, context.ServiceProvider, context.Context, true); using (currentPrincipalAccessor.Change(claimsPrincipal!)) { await next(context, exception); } } - protected virtual async Task HandleDynamicClaimsPrincipalAsync(ClaimsPrincipal? claimsPrincipal, IServiceProvider serviceProvider, HubCallerContext hubCallerContext) + protected virtual async Task HandleDynamicClaimsPrincipalAsync(ClaimsPrincipal? claimsPrincipal, IServiceProvider serviceProvider, HubCallerContext hubCallerContext, bool skipCheckDynamicClaimsInterval) { if (claimsPrincipal?.Identity != null && claimsPrincipal.Identity.IsAuthenticated && - serviceProvider.GetRequiredService>().Value.IsDynamicClaimsEnabled) + serviceProvider.GetRequiredService>().Value + .IsDynamicClaimsEnabled) { + var checkDynamicClaimsInterval = serviceProvider.GetRequiredService>().Value.CheckDynamicClaimsInterval; + if (!skipCheckDynamicClaimsInterval && + checkDynamicClaimsInterval.HasValue && + hubCallerContext.Items.TryGetValue(nameof(HandleDynamicClaimsPrincipalAsync), out var lastCheckDynamicClaimsTime) && + lastCheckDynamicClaimsTime is DateTime lastCheckDynamicClaimsTimeValue) + { + if (DateTime.UtcNow.Subtract(lastCheckDynamicClaimsTimeValue) < checkDynamicClaimsInterval.Value) + { + // Dynamic claims are not checked because the interval has not passed yet. + return; + } + } + + hubCallerContext.Items[nameof(HandleDynamicClaimsPrincipalAsync)] = DateTime.UtcNow; + claimsPrincipal = claimsPrincipal.Identity is ClaimsIdentity identity - ? new ClaimsPrincipal(new ClaimsIdentity(claimsPrincipal.Claims, claimsPrincipal.Identity.AuthenticationType, identity.NameClaimType, identity.RoleClaimType)) - : new ClaimsPrincipal(new ClaimsIdentity(claimsPrincipal.Claims, claimsPrincipal.Identity.AuthenticationType)); + ? new ClaimsPrincipal(new ClaimsIdentity(claimsPrincipal.Claims, + claimsPrincipal.Identity.AuthenticationType, identity.NameClaimType, identity.RoleClaimType)) + : new ClaimsPrincipal(new ClaimsIdentity(claimsPrincipal.Claims, + claimsPrincipal.Identity.AuthenticationType)); - claimsPrincipal = await serviceProvider.GetRequiredService().CreateDynamicAsync(claimsPrincipal); + claimsPrincipal = await serviceProvider.GetRequiredService() + .CreateDynamicAsync(claimsPrincipal); if (claimsPrincipal.Identity?.IsAuthenticated == false) { hubCallerContext.Abort();