如何在 Dot Net Core 2.2、JWT 中为每个用户创建 DBContext/Tenant 工厂
How to create DBContext/Tenant Factory per user in Dot Net Core 2.2, JWT
我的网络 API 应用程序中有两个 DBContext。第一个是让我所有的客户都使用他们的连接字符串,第二个是真正的应用程序数据库。
登录控制器使用 MyClientContext & 其他所有控制器使用 MyContext
我的 startup.cs
长相
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
services.AddDbContext<MyContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("MyContext")));
services.AddDbContext<MyClientContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("MyClientContext")));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<MyContext>();
context.Database.Migrate(); // Code First Migrations for App DB
var context2 = serviceScope.ServiceProvider.GetRequiredService<MyClientContext>();
context2.Database.Migrate(); // Code First Migrations for Clients DB
}
app.UseCors("AllowSpecificOrigin");
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseMvc();
}
登录成功后,我发出看起来像
的JWT令牌
private string GenerateJSONWebToken(UserAuth userInfo)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub, userInfo.UserName),
new Claim(JwtRegisteredClaimNames.Email, userInfo.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], claims,
expires: DateTime.Now.AddHours(24), signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
在这里,我在启动文件中为真实数据库分配了ConnectionString。我想在用户登录时分配它。我该如何实现?
我已经对我的代码进行了以下更改,并且现在可以按预期工作。它可能对其他人有用。
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddDbContext<MyContext>((serviceProvider, options) =>
{
var httpContext = serviceProvider.GetService<IHttpContextAccessor>().HttpContext;
var connection = GetConnection(httpContext);
options.UseNpgsql(connection);
});
private string GetConnection(HttpContext httpContext)
{
var UserName = httpContext?.User?.FindFirst(JwtRegisteredClaimNames.Jti)?.Value;
// Here extract ConnectionString from "MyClientContext"'s DB
}
对于 Code First DB 迁移,我将 Database.Migrate()
移至其 Class
public MyContext (DbContextOptions<MyContext> options)
: base(options)
{
Database.Migrate();
}
这对我来说很好。
我的网络 API 应用程序中有两个 DBContext。第一个是让我所有的客户都使用他们的连接字符串,第二个是真正的应用程序数据库。
登录控制器使用 MyClientContext & 其他所有控制器使用 MyContext
我的 startup.cs
长相
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
services.AddDbContext<MyContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("MyContext")));
services.AddDbContext<MyClientContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("MyClientContext")));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<MyContext>();
context.Database.Migrate(); // Code First Migrations for App DB
var context2 = serviceScope.ServiceProvider.GetRequiredService<MyClientContext>();
context2.Database.Migrate(); // Code First Migrations for Clients DB
}
app.UseCors("AllowSpecificOrigin");
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseMvc();
}
登录成功后,我发出看起来像
的JWT令牌private string GenerateJSONWebToken(UserAuth userInfo)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub, userInfo.UserName),
new Claim(JwtRegisteredClaimNames.Email, userInfo.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], claims,
expires: DateTime.Now.AddHours(24), signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
在这里,我在启动文件中为真实数据库分配了ConnectionString。我想在用户登录时分配它。我该如何实现?
我已经对我的代码进行了以下更改,并且现在可以按预期工作。它可能对其他人有用。
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddDbContext<MyContext>((serviceProvider, options) =>
{
var httpContext = serviceProvider.GetService<IHttpContextAccessor>().HttpContext;
var connection = GetConnection(httpContext);
options.UseNpgsql(connection);
});
private string GetConnection(HttpContext httpContext)
{
var UserName = httpContext?.User?.FindFirst(JwtRegisteredClaimNames.Jti)?.Value;
// Here extract ConnectionString from "MyClientContext"'s DB
}
对于 Code First DB 迁移,我将 Database.Migrate()
移至其 Class
public MyContext (DbContextOptions<MyContext> options)
: base(options)
{
Database.Migrate();
}
这对我来说很好。