You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor API项目中ILoggerProvider如何获取用户名?

问题描述

我想要构建自定义ILoggerProvider,使其具备获取用户名的功能,该如何实现?我使用外部OIDC服务,在API中已配置如下认证代码:

builder.Services
.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
    options.Authority = "https://xxxx/auth/realms/dev";
    options.TokenValidationParameters.ValidateAudience = false;
});

同时已注册自定义DbLoggerProvider:

builder.Services.AddScoped<ILoggerProvider,DbLoggerProvider>();

当我在DbLoggerProvider的构造函数中注入AuthenticationStateProvider时,构建时出现报错:

System.AggregateException
 Message=Some services are not able to be constructed
 Source=Microsoft.Extensions.DependencyInjection
 StackTrace:
 at
 Microsoft.Extensions.DependencyInjection.ServiceProvider. .ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
at 
Microsoft.Extensions.DependencyInjection.ServiceCollection 
ContainerBuilderExtensions.BuildServiceProvider 
(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
at Program.<Main>$(String[] args) in D:\x\Server\Program.cs:line 
153
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
InvalidOperationException: Error while validating the service 
descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostApplicationLifetime Lifetime: Singleton ImplementationType: Microsoft.Extensions.Hosting.Internal.ApplicationLifetime': Unable to resolve service for type 'Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider' while attempting to activate 'x.Server.Core.Providers.DbLoggerProvider'.
Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 
'Microsoft.AspNetCore.Components.Authorization. 
AuthenticationStateProvider' while attempting to activate 
'x.Server.Core.Providers.DbLoggerProvider'.

在控制器中我通过以下代码获取用户名:

string login = User.Claims.Where(p => p.Type == "preferred_username").First().Value;

请问如何在LoggerProvider中获取该用户名?另外,控制器并非通过AuthenticationStateProvider获取用户对象,它是如何实现的?

解决方案

一、在自定义ILoggerProvider中获取用户名的正确方式

你遇到的注入报错是因为AuthenticationStateProvider是Blazor专用服务,纯ASP.NET Core API场景下不会默认注册;且ILoggerProvider的生命周期是Singleton(即便你注册成Scoped,框架内部也会按Singleton处理),而用户上下文是请求级的(Scoped),直接在Provider构造函数注入请求级服务会导致生命周期冲突。

正确的做法是在自定义Logger(而非LoggerProvider)中通过IHttpContextAccessor获取当前请求的用户上下文,步骤如下:

  1. 注册IHttpContextAccessor服务:
builder.Services.AddHttpContextAccessor();
  1. 修改自定义DbLoggerProvider,在创建Logger实例时传入IHttpContextAccessor:
public class DbLoggerProvider : ILoggerProvider
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public DbLoggerProvider(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public ILogger CreateLogger(string categoryName)
    {
        return new DbLogger(_httpContextAccessor);
    }

    public void Dispose() { }
}
  1. 在自定义DbLogger中获取用户名:
public class DbLogger : ILogger
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public DbLogger(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public IDisposable BeginScope<TState>(TState state) => null;

    public bool IsEnabled(LogLevel logLevel) => true;

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        // 获取当前请求的用户名,无用户时返回"匿名用户"
        var userName = _httpContextAccessor.HttpContext?.User?.Claims
            .FirstOrDefault(c => c.Type == "preferred_username")?.Value ?? "匿名用户";

        // 后续执行写入数据库的逻辑,带上userName即可
        // ...
    }
}
  1. 按框架规范将LoggerProvider注册为Singleton:
builder.Services.AddSingleton<ILoggerProvider, DbLoggerProvider>();

二、控制器中获取用户对象的原理

控制器中的User属性是ASP.NET Core框架自动注入的,本质是直接读取当前请求的HttpContext.User:

  • 配置JWT认证后,认证中间件会在请求到达时解析Bearer令牌,将令牌中的声明信息解析到HttpContext.User中。
  • 控制器基类(ControllerBase)内置了HttpContext属性,可直接访问User;而AuthenticationStateProvider是Blazor场景下专门处理组件用户状态的服务,和API控制器的用户获取逻辑完全无关。

内容的提问来源于stack exchange,提问作者Dorian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 05:22:52