From 33dde1b7b6db6f420feba34b4d16d0efa6a00313 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 30 Jan 2026 10:43:35 +0800 Subject: [PATCH 1/4] feat(WebClientServer): add UserName property --- .../Components/ConnectionHub/ConnectionHub.cs | 14 ++++++++++++++ src/BootstrapBlazor/Services/WebClientService.cs | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs b/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs index 94f33a949fb..2f27f090299 100644 --- a/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs +++ b/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone +using Microsoft.AspNetCore.Components.Authorization; + namespace BootstrapBlazor.Components; /// @@ -32,6 +34,11 @@ public class ConnectionHub : BootstrapModuleComponentBase [NotNull] private IOptions? BootstrapBlazorOptions { get; set; } + [Inject] + [NotNull] + private AuthenticationStateProvider? AuthenticationStateProvider { get; set; } + + private IIpLocatorProvider? _ipLocatorProvider; private ThrottleOptions? _throttleOptions; @@ -77,6 +84,13 @@ await dispatch.ThrottleAsync(async () => _ipLocatorProvider ??= IpLocatorFactory.Create(BootstrapBlazorOptions.Value.IpLocatorOptions.ProviderName); client.City = await _ipLocatorProvider.Locate(client.Ip); } + + var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + var identity = state.User.Identity; + if (identity is { IsAuthenticated: true }) + { + client.UserName = identity.Name; + } ConnectionService.AddOrUpdate(client); }); } diff --git a/src/BootstrapBlazor/Services/WebClientService.cs b/src/BootstrapBlazor/Services/WebClientService.cs index f9de69e357c..fa17f100159 100644 --- a/src/BootstrapBlazor/Services/WebClientService.cs +++ b/src/BootstrapBlazor/Services/WebClientService.cs @@ -180,4 +180,10 @@ public class ClientInfo /// Gets or sets Browser Engine Info /// public string? Engine { get; set; } + + /// + /// 获得/设置 当前已登录用户账号 + /// Gets or sets currently logged-in user account + /// + public string? UserName { get; set; } } From ab76df12688f4430bd79c46ad60f899c7feebe8d Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 30 Jan 2026 11:36:51 +0800 Subject: [PATCH 2/4] =?UTF-8?q?test:=20=E5=A2=9E=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Services/ConnectionHubTest.cs | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/UnitTest/Services/ConnectionHubTest.cs b/test/UnitTest/Services/ConnectionHubTest.cs index f33ec35590c..95fb2e273e4 100644 --- a/test/UnitTest/Services/ConnectionHubTest.cs +++ b/test/UnitTest/Services/ConnectionHubTest.cs @@ -3,8 +3,10 @@ // See the LICENSE file in the project root for more information. // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone +using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.Options; using Microsoft.JSInterop; +using System.Security.Claims; namespace UnitTest.Services; @@ -17,6 +19,9 @@ public async Task Callback_Ok() context.JSInterop.Mode = JSRuntimeMode.Loose; context.Services.AddBootstrapBlazor(); + var authorizationContext = new MockAuthenticationStateProvider(); + context.Services.AddScoped(p => authorizationContext); + var options = context.Services.GetRequiredService>(); options.Value.ConnectionHubOptions = new() { @@ -36,6 +41,7 @@ await cut.InvokeAsync(async () => await Task.Delay(100); client.SetData(new ClientInfo() { Id = "test_id", Ip = "::1" }); }); + await cut.Instance.Callback(new ClientInfo { Id = "test_id", Ip = "::1" }); }); Assert.Equal(1, service.Count); @@ -49,12 +55,15 @@ await cut.InvokeAsync(async () => // 触发 Beat 时间 await Task.Delay(200); + authorizationContext.SetAuthorized("mock_user"); await cut.InvokeAsync(async () => { await cut.Instance.Callback(new ClientInfo { Id = "test_id", Ip = "::1" }); }); Assert.True(service.TryGetValue("test_id", out var item)); Assert.NotNull(item?.ClientInfo); + Assert.Equal("mock_user", item.ClientInfo.UserName); + Assert.True(item?.ConnectionTime < DateTimeOffset.Now); cut.Dispose(); @@ -155,4 +164,24 @@ public void ConnectionService_Ok() var d = service as IDisposable; d?.Dispose(); } + + class MockAuthenticationStateProvider : AuthenticationStateProvider + { + ClaimsPrincipal _claim = new(); + public override async Task GetAuthenticationStateAsync() + { + await Task.Yield(); + + var state = new AuthenticationState(_claim); + return state; + } + + public void SetAuthorized(string userName) + { + _claim = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] + { + new(ClaimTypes.Name, userName), + }, "mock")); + } + } } From e1bd35c5551b52572d8257b7ca50f8823c4e22da Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 30 Jan 2026 11:43:39 +0800 Subject: [PATCH 3/4] chore: bump version 10.3.0 --- src/BootstrapBlazor/BootstrapBlazor.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index aa82b7cd133..10caab2a03a 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 10.2.4-beta01 + 10.3.0 From e2614295012779c10ab7fe90b35936c65b82faa6 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 30 Jan 2026 11:45:48 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E5=8F=96?= =?UTF-8?q?=E5=80=BC=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/ConnectionHub/ConnectionHub.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs b/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs index 2f27f090299..b64071af55a 100644 --- a/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs +++ b/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs @@ -4,6 +4,7 @@ // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.DependencyInjection; namespace BootstrapBlazor.Components; @@ -36,7 +37,7 @@ public class ConnectionHub : BootstrapModuleComponentBase [Inject] [NotNull] - private AuthenticationStateProvider? AuthenticationStateProvider { get; set; } + private IServiceProvider? Provider { get; set; } private IIpLocatorProvider? _ipLocatorProvider; @@ -85,11 +86,15 @@ await dispatch.ThrottleAsync(async () => client.City = await _ipLocatorProvider.Locate(client.Ip); } - var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); - var identity = state.User.Identity; - if (identity is { IsAuthenticated: true }) + var authenticationStateProvider = Provider.GetService(); + if (authenticationStateProvider != null) { - client.UserName = identity.Name; + var state = await authenticationStateProvider.GetAuthenticationStateAsync(); + var identity = state.User.Identity; + if (identity is { IsAuthenticated: true }) + { + client.UserName = identity.Name; + } } ConnectionService.AddOrUpdate(client); });