首页 文章

WebAPI ASP Net Core JWT承载认证“签名无效”

提问于
浏览
0

我一直在尝试使用JWT承载认证开发一个简单的Web API . 到目前为止,我已经完全开发了一个应用程序,现在我需要一个Web API来提供与其他技术的通信 .

要开始我的API,我在这里找到了一个简单的例子:https://medium.com/@renato.groffe/asp-net-core-2-0-autentica%C3%A7%C3%A3o-em-apis-utilizando-jwt-json-web-tokens-4b1871efd

代码可在此处获取:https://github.com/renatogroffe/ASPNETCore2_JWT/tree/master/APIAlturas

我能够测试这个项目,它可以与JWT承载认证一起使用 .

当我不得不在我的控制器中执行一些依赖注入以从我的存储库中检索数据时,问题就出现了 . 我的API没有解析我的依赖项,所以我不得不在我的Startup.cs文件中进行一些更改 .

因此,我的项目中唯一与上面示例不同的是Startup.cs文件 .

这里发生的是我的API生成一个令牌,当我尝试将它发送到我的其他控制器(在 Headers 中)时,它返回:"Bearer error=" invalid_token ", error_description="签名无效“

My guess is that something in my Startup.cs file is messing with my authentication.

这是我注意到的另一件事,我在appsettings.json文件中设置了令牌配置 . 当我调用生成令牌的方法时,我的tokenConfigurations对象中没有设置这些参数 . 但是,调试代码,我的startup.cs文件接收参数 . 当我调用控制器时,这些参数现在在此对象中为null .

public object Post([FromBody]User usuario,[FromServices]SigningConfigurations signingConfigurations, [FromServices]TokenConfigurations tokenConfigurations){     ... my code        

}

这是我的startup.cs文件

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Stratec.WebAPI;
using Stratec.Configuration;
using Stratec.Domain;
using Autofac;
using Hangfire;
using Microsoft.AspNetCore.Http;
using Stratec.Web;
using Hangfire.SqlServer;

namespace Stratec.WebAPI
{
    public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup(IHostingEnvironment env)
        {
            Configuration = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                // .AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true)
                //.AddXmlFile($"appsettings.{env.EnvironmentName}.xml", optional: true)
                .AddEnvironmentVariables()
                .Build();

            Configuracao.Configuration = Configuration;
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<UsersDAO>();

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            var signingConfigurations = new SigningConfigurations();
            services.AddSingleton(signingConfigurations);

            var tokenConfigurations = new TokenConfigurations();
            new ConfigureFromConfigurationOptions<TokenConfigurations>(
                Configuration.GetSection("TokenConfigurations"))
                    .Configure(tokenConfigurations);
            services.AddSingleton(tokenConfigurations);

            services.AddAuthentication(authOptions =>
            {
                authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(bearerOptions =>
            {
                var paramsValidation = bearerOptions.TokenValidationParameters;
                paramsValidation.IssuerSigningKey = signingConfigurations.Key;
                paramsValidation.ValidAudience = tokenConfigurations.Audience;
                paramsValidation.ValidIssuer = tokenConfigurations.Issuer;

                // Valida a assinatura de um token recebido
                paramsValidation.ValidateIssuerSigningKey = true;

                // Verifica se um token recebido ainda é válido
                paramsValidation.ValidateLifetime = true;

                // Tempo de tolerância para a expiração de um token (utilizado
                // caso haja problemas de sincronismo de horário entre diferentes
                // computadores envolvidos no processo de comunicação)
                paramsValidation.ClockSkew = TimeSpan.Zero;
            });

            // Ativa o uso do token como forma de autorizar o acesso
            // a recursos deste projeto
            services.AddAuthorization(auth =>
            {
                auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                    .RequireAuthenticatedUser().Build());
            });

            services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("ConexaoPadrao")));
            JobStorage.Current = new SqlServerStorage(Configuration.GetConnectionString("ConexaoPadrao"));
            // services.AddMvcCore();
            services.AddMvc();

            var assemblies = new[]
            {
                typeof(Startup).Assembly,
                typeof(Colaborador).Assembly
            };

            //IContainer container = null;

            var serviceProvider = ConfigurationApplication.Inicialize(services, Configuration, assemblies);

            //GlobalConfiguration.Configuration.UseAutofacActivator(container);

            return serviceProvider;
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMiddleware<UnitOfWorkMiddleware>();
            app.UseMiddleware<AutenticacaoMiddleware<Autenticacao>>();

            app.UseMvc();            

            app.UseStaticFiles();
        }
    }
}

有人能帮助我吗?我一直试图在这里找到问题,但我找不到类似的问题 .

1 回答

  • 1
    POST http://localhost:56435/api/login HTTP/1.1
    Content-Type : application/json
    
    {userId:"usuario01",accessKey:"94be650011cf412ca906fc335f615cdc"}
    

    回应将是:

    HTTP/1.1 200 OK
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=utf-8
    Server: Kestrel
    X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcc3RyZWFteHVcRG93bmxvYWRzXEFTUE5FVENvcmUyX0pXVC1tYXN0ZXJcQVNQTkVUQ29yZTJfSldULW1hc3RlclxBUElBbHR1cmFzXEFQSUFsdHVyYXNcYXBpXGxvZ2lu?=
    X-Powered-By: ASP.NET
    Date: Thu, 30 Aug 2018 01:12:10 GMT
    
    {
      "authenticated": true,
      "created": "2018-08-30 09:12:10",
      "expiration": "2018-08-30 09:13:10",
      "accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6WyJ1c3VhcmlvMDEiLCJ1c3VhcmlvMDEiXSwianRpIjoiZTk0ZDU3NTMwZTczNDMzMTlkYjVlN2EwMDY2YjQwOTUiLCJuYmYiOjE1MzU1OTE1MzAsImV4cCI6MTUzNTU5MTU5MCwiaWF0IjoxNTM1NTkxNTMwLCJpc3MiOiJFeGVtcGxvSXNzdWVyIiwiYXVkIjoiRXhlbXBsb0F1ZGllbmNlIn0.WR3V9kkI_Pyhpw-TnpbTsByB4JZa61PFymUGdm-3_CGInbOOH6RxbMchCdbojyflSZBf3d8O7RYiz2xiMoonkOcJc6gtO0ODCv-cUDPJYApwJVYOq1HEqSs0STvKdSjRZF6j0DM4WON6fpoVwKAq0rwng1aEf9bQue6Pl-fwbzbaCxhCrQtDyDYKyfO0tg-VMGQfMyV29Ab0s4W2L5bcB0w0jAgfFianAD2DKSDSVsDSiBTd7b-Np9OcEtBvXCkXMFEqGzkOIKGAR5kzTiOWPo_Dh9qOVlsooRtFbhOjxWqeYRR76fZ-OOt9Sg6eG5zu1T7lPNywKFeAznS2rss1ig",
      "message": "OK"
    }
    

    注意 expiration 这里表示 the access token will be expired in 1 min . 如果我在61secs之后发送带有这些令牌的请求:

    GET http://localhost:56435/api/ConversorAlturas/PesMetros/1.13 HTTP/1.1
    Authorization : Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6WyJ1c3VhcmlvMDEiLCJ1c3VhcmlvMDEiXSwianRpIjoiZTk0ZDU3NTMwZTczNDMzMTlkYjVlN2EwMDY2YjQwOTUiLCJuYmYiOjE1MzU1OTE1MzAsImV4cCI6MTUzNTU5MTU5MCwiaWF0IjoxNTM1NTkxNTMwLCJpc3MiOiJFeGVtcGxvSXNzdWVyIiwiYXVkIjoiRXhlbXBsb0F1ZGllbmNlIn0.WR3V9kkI_Pyhpw-TnpbTsByB4JZa61PFymUGdm-3_CGInbOOH6RxbMchCdbojyflSZBf3d8O7RYiz2xiMoonkOcJc6gtO0ODCv-cUDPJYApwJVYOq1HEqSs0STvKdSjRZF6j0DM4WON6fpoVwKAq0rwng1aEf9bQue6Pl-fwbzbaCxhCrQtDyDYKyfO0tg-VMGQfMyV29Ab0s4W2L5bcB0w0jAgfFianAD2DKSDSVsDSiBTd7b-Np9OcEtBvXCkXMFEqGzkOIKGAR5kzTiOWPo_Dh9qOVlsooRtFbhOjxWqeYRR76fZ-OOt9Sg6eG5zu1T7lPNywKFeAznS2rss1ig
    

    回应将是:

    HTTP/1.1 401 Unauthorized
    Server: Kestrel
    WWW-Authenticate: Bearer error="invalid_token", error_description="The token is expired"
    X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcc3RyZWFteHVcRG93bmxvYWRzXEFTUE5FVENvcmUyX0pXVC1tYXN0ZXJcQVNQTkVUQ29yZTJfSldULW1hc3RlclxBUElBbHR1cmFzXEFQSUFsdHVyYXNcYXBpXENvbnZlcnNvckFsdHVyYXNcUGVzTWV0cm9zXDEuMTM=?=
    X-Powered-By: ASP.NET
    Date: Thu, 30 Aug 2018 01:17:02 GMT
    Content-Length: 0
    

    请注意错误消息是 "invalid_token", error_description="The token is expired"

    我不确定你的到期时间是否为1分钟 . 但是,你最好先检查一下 . 如果它没有用,请转到第2步 .

    • 由于上面的代码中没有足够的信息,我建议您查看以下列表:

    一个) . 当你遭遇 invalid_token 时,你发送给控制器的持票人是什么?

    B) . 你的 Configuracao 是什么? Configuracao.Configuration = Configuration; 的陈述使我感到困惑 . 你能告诉我们 Configuracao 吗?

    B) . 我注意到你和教程都使用了自定义身份验证/授权方式而不是标准 UseAuthentication() . 我也不确定 app.UseMiddleware<AutenticacaoMiddleware<Autenticacao>>() 是什么意思 . 你能告诉我们 AutenticacaoMiddlewareAutenticacao 吗?

相关问题