ASP.NET Core 2.1 API JWT 令牌 Session.id 在每次请求时都会更改

Posted

技术标签:

【中文标题】ASP.NET Core 2.1 API JWT 令牌 Session.id 在每次请求时都会更改【英文标题】:ASP.NET Core 2.1 API JWT token Session.id changes on every request 【发布时间】:2019-02-02 20:42:45 【问题描述】:

我有一个使用 Angular 4 应用程序连接到的 asp.net core 2.1 API,并通过 JWT 令牌进行身份验证。我那里也有 2 个 SignalR 集线器。

身份验证效果很好,我确信它可以正常工作,因为登录后我可以访问已设置 [Authorize] 的方法和类。

问题是注入的_accessor.HttpContext.Session.Id 每次请求都会发生变化。所以真正的问题是我不能使用会话变量。

我不知所措,在我看来我在这里遗漏了一些东西。 有人可以帮我一些想法吗?非常感谢任何帮助。

到目前为止,这是我的 startup.cs:

public class Startup

    public Startup(IConfiguration configuration, IHostingEnvironment env)
    
        Configuration = configuration;
        if (env.IsDevelopment())
        
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.RollingFile(Path.Combine(env.ContentRootPath+"/logs/", "log-Date.txt"))
                //, outputTemplate: "MachineName EnvironmentUserName: Message:ljNewLineException"
                .WriteTo.Seq("http://192.168.1.164:5341")
                .Enrich.WithMachineName()
                .Enrich.WithEnvironmentUserName()
                .CreateLogger();
        
        else
        
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .WriteTo.RollingFile(Path.Combine(env.ContentRootPath + "/logs/", "log-Date.txt"))
                .Enrich.WithMachineName()
                .Enrich.WithEnvironmentUserName()
                .CreateLogger();
        
    

public IConfiguration Configuration  get; 

public void ConfigureServices(IServiceCollection services)

    var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
    services.AddDbContext<PaymentServicesContext>(options => options.UseSqlServer(Configuration.GetConnectionString("PaymentDatabase")));

    services.AddSession(options =>
    
        options.IdleTimeout = TimeSpan.FromMinutes(10);
        options.Cookie.HttpOnly = true;
    );

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddSessionStateTempDataProvider();

    services.AddAuthentication(options =>
    
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    )
    .AddJwtBearer(options =>
    
        options.TokenValidationParameters =
        new TokenValidationParameters
        
            LifetimeValidator = (before, expires, token, param) =>
            
                return expires > DateTime.UtcNow;
            ,
            ValidateAudience = false,
            ValidateIssuerSigningKey = true,
            ValidateIssuer = false,
            ValidateActor = false,
            ValidateLifetime = true,
            IssuerSigningKey = new SymmetricSecurityKey(key)
        ;
        options.Events = new JwtBearerEvents
        
            OnMessageReceived = context =>
            
                var accessToken = context.Request.Query["access_token"];
                var path = context.HttpContext.Request.Path;
                if (!string.IsNullOrEmpty(accessToken))
                
                    context.Token = accessToken;
                
                return Task.CompletedTask;
            
        ;
    );
    services.AddAutoMapper();
    services.AddCors();
    services.AddSignalR(options => options.EnableDetailedErrors = true);

    ///services
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    services.AddTransient<IBrainzService, BrainzService>();
    services.AddTransient<ISecurityService, SecurityService>();



public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();
    loggerFactory.AddSerilog();

    if (env.IsDevelopment())
    
        app.UseDeveloperExceptionPage();
    
    else
    
        app.UseExceptionHandler(builder =>
        
            builder.Run(async context =>
            
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

                var error = context.Features.Get<IExceptionHandlerFeature>();
                if (error != null)
                
                    
                    await context.Response.WriteAsync(error.Error.Message);
                
            );
        );
    


    app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials())
        .UseStaticFiles()
        .UseWebSockets();

    app.UseAuthentication();
    if (!env.IsDevelopment())
    
        app.UseHttpsRedirection();
    
    app.UseWebSockets();

    app.UseSignalR(
        routes =>
        
            routes.MapHub<MessagingHub>("/messagingHub");
            routes.MapHub<UpdatesHub>("/updatesHub");
        );

    app.UseSession();
    app.UseMvc();
  

【问题讨论】:

【参考方案1】:

配置有效。 问题是 Angular 的 HttpClient 默认不存储/获取/发送 cookie,因为我发现很难。 我所要做的就是在登录请求中添加withCredentials: true 选项,会话cookie 就会弹出到浏览器中! 要恢复会话,您必须将此选项添加到所有请求,API 将知道会话!

【讨论】:

【参考方案2】:

一种解决方案是创建一个Interceptor 以在所有请求离开客户端应用程序之前拦截它。这个tutorial 解释得很好。您还可以通过将withCredentials 设置为true,在每个请求级别上执行此操作。

const requestOptions = 
 headers: new HttpHeaders(
  'Authorization': "my-request-token"
 ),
 withCredentials: true
;

【讨论】:

以上是关于ASP.NET Core 2.1 API JWT 令牌 Session.id 在每次请求时都会更改的主要内容,如果未能解决你的问题,请参考以下文章

向 ASP.NET Core 2.1 Web API 添加 JWT 身份验证时是不是需要创建像 AspNetUsers 这样的表?

ASP.NET Core 2.1 Jwt 设置自定义声明

直接从令牌获取 JWT 声明,ASP Net Core 2.1

在 ASP.NET Core 2.1 Web 客户端中存储不记名令牌的位置

在c#asp.net core web api中创建jwt令牌[重复]

ASP.NET Core Web Api之JWT