簡體   English   中英

ASP.NET Core 2.1 API JWT 令牌 Session.id 在每次請求時都會更改

[英]ASP.NET Core 2.1 API JWT token Session.id changes on every request

我有一個 asp.net core 2.1 API,我使用它連接到 Angular 4 應用程序並通過 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:lj}{NewLine}{Exception}"
                .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();
  }
}

配置有效。 問題是 Angular 的 HttpClient 默認情況下不存儲/獲取/發送 cookie,因為我發現了困難的方法。 我所要做的就是向登錄請求添加{withCredentials: true }選項,然后會話 cookie 就會彈出到瀏覽器中! 要恢復會話,您必須將此選項添加到所有請求,API 將知道該會話!

一種解決方案是創建一個Interceptor以在請求離開客戶端應用程序之前攔截所有請求。 教程解釋得很好。 您還可以通過將withCredentials設置為true在每個請求級別執行此操作。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM