使用ASP .NET Core验证服务描述符时错误

发布于 2025-02-13 22:28:19 字数 7716 浏览 0 评论 0原文

我正在尝试在帐户控制器中的注销操作方法中创建注销机制。为此,我需要停用我的JWT令牌。我遵循本教程停用JWT令牌。在我的项目中应用此代码后,我的项目在运行该项目时显示错误。

我的代码如下。

startup.cs

      public void ConfigureServices(IServiceCollection services)
        {
            // New
            services.AddTransient<TokenManagerMiddleware>();
            services.AddTransient<ITokenManager, TokenManager>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            var authPol = new AuthorizationPolicyBuilder()
                                         .AddAuthenticationSchemes(
                                                         new string[] { 
           JwtBearerDefaults.AuthenticationScheme })
                                         .RequireAuthenticatedUser()
                                         .Build();
                      
            services.AddControllers(
            config => 
            {
                config.Filters.Add(new AuthorizeFilter(authPol));
            }).AddXmlSerializerFormatters()
            .AddXmlDataContractSerializerFormatters();

        services.AddDbContext<BikeStoresContext>();

        // JWT Token code is there below this...
        }


      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "BikeStoreAPI v1"));
            }

            app.UseMiddleware<TokenManagerMiddleware>();

            app.UseDeveloperExceptionPage();

            app.UseHttpsRedirection();

            app.UseRouting();


            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

tokenmanagermiddleware.cs

public class TokenManagerMiddleware : IMiddleware
{
    private readonly ITokenManager _tokenManager;

    public TokenManagerMiddleware(ITokenManager tokenManager)
    {
        _tokenManager = tokenManager;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        if (await _tokenManager.IsCurrentActiveToken())
        {
            await next(context);
            return;
        }
        context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    }
    
}

itokenmanager.cs

public interface ITokenManager
{
    Task<bool> IsCurrentActiveToken();

    Task DeactivateCurrentAsync();

    Task<bool> IsActiveAsync(string token);

    Task DeactivateAsync(string token);

    Task SetToken(string token);
}

tokenmanager.cs

public class TokenManager : ITokenManager
{
    private readonly IDistributedCache _cache;


    private readonly IHttpContextAccessor _httpContextAccessor;

    public TokenManager(IDistributedCache cache, IHttpContextAccessor httpContextAccessor)
    {
        _cache = cache;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task SetToken(string token)
    {
        await _cache.SetStringAsync(token, token);
    }

    public async Task<bool> IsCurrentActiveToken()
     => await IsActiveAsync(GetCurrentAsync());

    public async Task DeactivateCurrentAsync()
        => await DeactivateAsync(GetCurrentAsync());


    public async Task<bool> IsActiveAsync(string token)
        => await _cache.GetStringAsync(GetKey(token)) == null;

    public async Task DeactivateAsync(string token)
        => await _cache.SetStringAsync(GetKey(token),
            " ", new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow =
                    TimeSpan.FromMinutes(720)
            });

    private string GetCurrentAsync()
    {
        var authorizationHeader = _httpContextAccessor
            .HttpContext.Request.Headers["authorization"];

        return authorizationHeader == StringValues.Empty
            ? string.Empty
            : authorizationHeader.Single().Split(" ").Last();
    }

    private static string GetKey(string token)
    => $"tokens:{token}:deactivated";

}

accountscontroller.cs

UserManager<IdentityUser> userManager;
SignInManager<IdentityUser> signInManager;
RoleManager<IdentityRole> roleManager;

private readonly ITokenManager tokenManager;

public AccountsController(UserManager<IdentityUser> _userManager, SignInManager<IdentityUser> _signInManager, 
    RoleManager<IdentityRole> _roleManager, ITokenManager _tokenManager)
{
    userManager = _userManager;
    signInManager = _signInManager;
    roleManager = _roleManager;

    tokenManager = _tokenManager;
}

[HttpPost("logout")]
public async Task<IActionResult> Logout()
{
    await tokenManager.DeactivateCurrentAsync();
    return NoContent();
}

当我尝试运行该项目时,我会遇到此错误:

system.AggregateException hresult = 0x80131500消息=某些服务 无法构造(验证服务时出错 描述符的服务类型: bikestoreapi.middleware.tokenmanagermiddleware生命周期:瞬态 bikestoreapi.middleware.tokenmanagermiddleware': 无法解析类型的服务 'Microsoft.extensions.caching.distributed.IdistributedCache' 试图激活 'Bikestoreapi.Services.TokenManagerService.TokenManager')(错误 同时验证服务描述符的服务类型: Bikestoreapi.Services.TokenManagerService.ItokenManager Lifetime: 瞬态实现类型: Bikestoreapi.Services.TokenManagerService.TokenManager':无法 解决类型的服务 'Microsoft.extensions.caching.distributed.IdistributedCache' 试图激活 'Bikestoreapi.Services.TokenManagerService.TokenManager'。)
source = microsoft.extensions.ipendentencyindoction stacktrace:at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable1 serviceDescriptors, IServiceProviderEngine engine, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) at Microsoft.extensions.dependentiondoction.defaultserviceProviderFactory.CreateserviceProvider(iserviceCollection ContarerBuilder)at microsoft.extensions.hosting.hosting.internal.servicefactoryadapter 1.CreateserviceProvider(CreateserviceProvider) 集装箱) microsoft.extensions.hosting.hostbuilder.createserviceprovider()at microsoft.extensions.hosting.hostbuilder.build()at bikestoreapi.program.main(string [] args)in C:\ users \ abhishek \ source \ repos \ bikestore \ bikestoreapi \ program.cs:line 16

这个例外最初是在此通话堆栈中抛出的: [外部代码]

内部异常1:InvalidOperationException:验证时错误 服务描述符的ServiceType: bikestoreapi.middleware.tokenmanagermiddleware生命周期:瞬态 bikestoreapi.middleware.tokenmanagermiddleware': 无法解析类型的服务 'Microsoft.extensions.caching.distributed.IdistributedCache' 试图激活 'Bikestoreapi.Services.TokenManagerService.TokenManager'。

内部异常2:InvalidOperationException:无法解析 类型的服务 'Microsoft.extensions.caching.distributed.IdistributedCache' 试图激活 'Bikestoreapi.Services.TokenManagerService.TokenManager'。

我经历了多次的每个步骤和编码,但我不知道出了什么问题。你能帮我吗

编辑 我在startup.cs中添加了下面的给定代码,但是当调用登录API生成JWT令牌时,遇到此错误。

  services.AddDistributedRedisCache(r => { r.Configuration = Configuration["redis:connectionString"]; });

I am trying to create a logout mechanism in logout action method in Accounts Controller. For that, I need to deactivate my JWT token. I followed this tutorial to deactivate JWT token. My project is showing error when I run the project after applying this code in my project.

Canceling JWT tokens in .NET Core

My code is as follows.

Startup.cs

      public void ConfigureServices(IServiceCollection services)
        {
            // New
            services.AddTransient<TokenManagerMiddleware>();
            services.AddTransient<ITokenManager, TokenManager>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            var authPol = new AuthorizationPolicyBuilder()
                                         .AddAuthenticationSchemes(
                                                         new string[] { 
           JwtBearerDefaults.AuthenticationScheme })
                                         .RequireAuthenticatedUser()
                                         .Build();
                      
            services.AddControllers(
            config => 
            {
                config.Filters.Add(new AuthorizeFilter(authPol));
            }).AddXmlSerializerFormatters()
            .AddXmlDataContractSerializerFormatters();

        services.AddDbContext<BikeStoresContext>();

        // JWT Token code is there below this...
        }


      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "BikeStoreAPI v1"));
            }

            app.UseMiddleware<TokenManagerMiddleware>();

            app.UseDeveloperExceptionPage();

            app.UseHttpsRedirection();

            app.UseRouting();


            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

TokenManagerMiddleware.cs

public class TokenManagerMiddleware : IMiddleware
{
    private readonly ITokenManager _tokenManager;

    public TokenManagerMiddleware(ITokenManager tokenManager)
    {
        _tokenManager = tokenManager;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        if (await _tokenManager.IsCurrentActiveToken())
        {
            await next(context);
            return;
        }
        context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    }
    
}

ITokenManager.cs

public interface ITokenManager
{
    Task<bool> IsCurrentActiveToken();

    Task DeactivateCurrentAsync();

    Task<bool> IsActiveAsync(string token);

    Task DeactivateAsync(string token);

    Task SetToken(string token);
}

TokenManager.cs

public class TokenManager : ITokenManager
{
    private readonly IDistributedCache _cache;


    private readonly IHttpContextAccessor _httpContextAccessor;

    public TokenManager(IDistributedCache cache, IHttpContextAccessor httpContextAccessor)
    {
        _cache = cache;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task SetToken(string token)
    {
        await _cache.SetStringAsync(token, token);
    }

    public async Task<bool> IsCurrentActiveToken()
     => await IsActiveAsync(GetCurrentAsync());

    public async Task DeactivateCurrentAsync()
        => await DeactivateAsync(GetCurrentAsync());


    public async Task<bool> IsActiveAsync(string token)
        => await _cache.GetStringAsync(GetKey(token)) == null;

    public async Task DeactivateAsync(string token)
        => await _cache.SetStringAsync(GetKey(token),
            " ", new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow =
                    TimeSpan.FromMinutes(720)
            });

    private string GetCurrentAsync()
    {
        var authorizationHeader = _httpContextAccessor
            .HttpContext.Request.Headers["authorization"];

        return authorizationHeader == StringValues.Empty
            ? string.Empty
            : authorizationHeader.Single().Split(" ").Last();
    }

    private static string GetKey(string token)
    => 
quot;tokens:{token}:deactivated";

}

AccountsController.cs

UserManager<IdentityUser> userManager;
SignInManager<IdentityUser> signInManager;
RoleManager<IdentityRole> roleManager;

private readonly ITokenManager tokenManager;

public AccountsController(UserManager<IdentityUser> _userManager, SignInManager<IdentityUser> _signInManager, 
    RoleManager<IdentityRole> _roleManager, ITokenManager _tokenManager)
{
    userManager = _userManager;
    signInManager = _signInManager;
    roleManager = _roleManager;

    tokenManager = _tokenManager;
}

[HttpPost("logout")]
public async Task<IActionResult> Logout()
{
    await tokenManager.DeactivateCurrentAsync();
    return NoContent();
}

When I tried to run the project, I am getting this error:

System.AggregateException HResult=0x80131500 Message=Some services
are not able to be constructed (Error while validating the service
descriptor 'ServiceType:
BikeStoreAPI.Middleware.TokenManagerMiddleware Lifetime: Transient
ImplementationType: BikeStoreAPI.Middleware.TokenManagerMiddleware':
Unable to resolve service for type
'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while
attempting to activate
'BikeStoreAPI.Services.TokenManagerService.TokenManager'.) (Error
while validating the service descriptor 'ServiceType:
BikeStoreAPI.Services.TokenManagerService.ITokenManager Lifetime:
Transient ImplementationType:
BikeStoreAPI.Services.TokenManagerService.TokenManager': Unable to
resolve service for type
'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while
attempting to activate
'BikeStoreAPI.Services.TokenManagerService.TokenManager'.)
Source=Microsoft.Extensions.DependencyInjection StackTrace: at
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable1 serviceDescriptors, IServiceProviderEngine engine, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder) at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter1.CreateServiceProvider(Object
containerBuilder) at
Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider() at
Microsoft.Extensions.Hosting.HostBuilder.Build() at
BikeStoreAPI.Program.Main(String[] args) in
C:\Users\Abhishek\source\repos\BikeStore\BikeStoreAPI\Program.cs:line
16

This exception was originally thrown at this call stack:
[External Code]

Inner Exception 1: InvalidOperationException: Error while validating
the service descriptor 'ServiceType:
BikeStoreAPI.Middleware.TokenManagerMiddleware Lifetime: Transient
ImplementationType: BikeStoreAPI.Middleware.TokenManagerMiddleware':
Unable to resolve service for type
'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while
attempting to activate
'BikeStoreAPI.Services.TokenManagerService.TokenManager'.

Inner Exception 2: InvalidOperationException: Unable to resolve
service for type
'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while
attempting to activate
'BikeStoreAPI.Services.TokenManagerService.TokenManager'.

I went through each step and code multiple times but I don't know what went wrong. Can you please help me.

Edit
I added below given code in startup.cs but getting this error when Login API is called to generate JWT token.

  services.AddDistributedRedisCache(r => { r.Configuration = Configuration["redis:connectionString"]; });

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

霞映澄塘 2025-02-20 22:28:19

仔细阅读异常消息。

在尝试激活'bikestoreapi.services.tokenmanagerservice.tokenmanager

时,无法解决'microsoft.extensions.caching.distributed.idistributedCache'类型的服务。

。代码> TokenManager 尝试获得服务。

您需要为 iDistributedCache 取决于分布式缓存提供商您想使用的。

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<TokenManagerMiddleware>();
    services.AddTransient<ITokenManager, TokenManager>();
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Register IDistributedCache service
    services.AddDistributedRedisCache(r => { r.Configuration = Configuration["redis:connectionString"]; 

    ...

}

Read the exception message carefully.

Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'BikeStoreAPI.Services.TokenManagerService.TokenManager

It says that you didn't register the service for IDistributedCache while TokenManager attempts to get the service.

You need to register the service for IDistributedCache depending on the distributed cache provider that you want to use.

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<TokenManagerMiddleware>();
    services.AddTransient<ITokenManager, TokenManager>();
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Register IDistributedCache service
    services.AddDistributedRedisCache(r => { r.Configuration = Configuration["redis:connectionString"]; 

    ...

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文