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 核心 2.1 API 连接到使用和 Angular 4 应用程序并通过 JWT 令牌进行身份验证。我也有 2 个 SignalR 集线器。
身份验证工作正常,我确信它工作正常,因为登录后我可以访问这些方法并且 类 我已将 [Authorize] 设置为 on。
问题是注入的 _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 默认情况下不 store/get/send cookie,因为我发现了困难的方法。
我所要做的就是向登录请求添加 {withCredentials: true }
选项,会话 cookie 就会弹出到浏览器中!
要恢复会话,您必须将此选项添加到所有请求,API 将知道该会话!
一个解决方案是创建一个 Interceptor
以在请求离开客户端应用程序之前拦截所有请求。这个 tutorial 解释得很好。您还可以通过将 withCredentials
设置为 true
.
在每个请求级别执行此操作
const requestOptions = {
headers: new HttpHeaders({
'Authorization': "my-request-token"
}),
withCredentials: true
};
我有一个 asp.net 核心 2.1 API 连接到使用和 Angular 4 应用程序并通过 JWT 令牌进行身份验证。我也有 2 个 SignalR 集线器。
身份验证工作正常,我确信它工作正常,因为登录后我可以访问这些方法并且 类 我已将 [Authorize] 设置为 on。
问题是注入的 _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 默认情况下不 store/get/send cookie,因为我发现了困难的方法。
我所要做的就是向登录请求添加 {withCredentials: true }
选项,会话 cookie 就会弹出到浏览器中!
要恢复会话,您必须将此选项添加到所有请求,API 将知道该会话!
一个解决方案是创建一个 Interceptor
以在请求离开客户端应用程序之前拦截所有请求。这个 tutorial 解释得很好。您还可以通过将 withCredentials
设置为 true
.
const requestOptions = {
headers: new HttpHeaders({
'Authorization': "my-request-token"
}),
withCredentials: true
};