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();