【问题标题】:How to create DBContext/Tenant Factory per user in Dot Net Core 2.2, JWT如何在 Dot Net Core 2.2、JWT 中为每个用户创建 DBContext/Tenant Factory
【发布时间】:2019-06-15 14:04:29
【问题描述】:

我的 Web 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。我想在用户登录时分配这个。我该如何实现?

【问题讨论】:

  • 首先,您的问题应该有一个问号,因为这是一个问答网站。其次,“我该如何解决”,解决什么?您没有描述问题
  • @MindSwipe,我更新了我的问题。
  • 为什么每个用户都应该拥有自己的 DBContext?
  • @MindSwipe,我们有一种情况,我的应用程序客户端将使用具有相同公共数据库架构的个人数据库,但网络应用程序只是一个。所以我们想将连接字符串更改为他/她各自的个人数据库.
  • 但是为什么要为成百上千的客户创建可能成百上千的数据库呢?这似乎是一个非常糟糕的做法

标签: c# jwt asp.net-core-2.2


【解决方案1】:

我已经对我的代码进行了以下更改,并且它现在按预期工作。它可能对其他人有用。

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 数据库迁移,我将 Database.Migrate() 移至其类

public MyContext (DbContextOptions<MyContext> options)
            : base(options)
        {
            Database.Migrate();
        }

这对我来说很好。

【讨论】:

  • 你是一个节省时间的人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 2019-08-08
  • 2021-01-04
  • 1970-01-01
  • 2019-12-01
  • 2019-01-29
相关资源
最近更新 更多