我可以在ASP.NET Core启动期间访问数据库吗?

时间:2016-08-02 19:07:20

标签: c# .net asp.net-core asp.net-core-mvc .net-core

我最近一直在研究.NET Core Web API。我刚刚使用JWT尝试进行身份验证,遵循https://stormpath.com/blog/token-authentication-asp-net-core上的指南。

一切顺利,直到我不得不用GetIdentity方法用数据库查询替换硬编码的用户名和密码,并意识到我不知道如何从这个文件中访问数据库!

我所指的方法显示在第70行的下面链接中。 https://github.com/nbarbettini/SimpleTokenProvider/blob/master/test/SimpleTokenProvider.Test/Startup.Auth.cs

我的问题如下。

  1. 我可以在这里访问数据库吗?如果是这样的话?
  2. 这应该是GetIdentity方法的位置,还是有更好的方法?

4 个答案:

答案 0 :(得分:13)

是的,您可以访问数据库!在Configure方法中运行的代码可以访问ConfigureServices方法中添加的任何服务,包括数据库上下文等。

例如,如果您有一个简单的实体框架上下文:

using Microsoft.EntityFrameworkCore;
using SimpleTokenProvider.Test.Models;

namespace SimpleTokenProvider.Test
{
    public class SimpleContext : DbContext
    {
        public SimpleContext(DbContextOptions<SimpleContext> options)
            : base(options)
        {
        }

        public DbSet<User> Users { get; set; }
    }
}

然后将其添加到ConfigureServices

services.AddDbContext<SimpleContext>(opt => opt.UseInMemoryDatabase());

然后,您可以在设置中间件时访问它:

var context = app.ApplicationServices.GetService<SimpleContext>();

app.UseSimpleTokenProvider(new TokenProviderOptions
{
    Path = "/api/token",
    Audience = "ExampleAudience",
    Issuer = "ExampleIssuer",
    SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256),
    IdentityResolver = (username, password) => GetIdentity(context, username, password)
});

稍微改写GetIdentity方法:

private Task<ClaimsIdentity> GetIdentity(SimpleContext context, string username, string password)
{
    // Access the database using the context
    // Here you'd need to do things like hash the password
    // and do a lookup to see if the user + password hash exists
}

我是原始样本的作者。对不起,最初还不清楚!我尝试以一种易于提供自己的功能的方式编写IdentityResolver委托 - 比如与您自己的数据库集成(如上所述),或者将其挂钩到ASP.NET Core Identity。当然,您可以随意丢弃我的代码并做更好的事情。 :)

答案 1 :(得分:6)

在.NET CORE 2.1上,只需将上下文作为参数传递给Configure方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, YourDbContext context)
{
        //do whatever you want with the context here...
}

答案 2 :(得分:3)

接受的答案不适用于范围服务(如果您使用Entity Framework并使用AddDbContext然后使用scoped添加上下文,则按请求创建this is the case服务)。

您可以在启动时按如下方式使用作用域服务(source):

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    using (var serviceScope = app.ApplicationServices.CreateScope())
    {
        var services = serviceScope.ServiceProvider;
        var myDbContext = services.GetService<MyDbContext>();
    }
}

或将其传递给Configure方法的参数,如答案 juanora

答案 3 :(得分:0)

我可能在某些其他级别上错了,但我找到的解决方案是创建一个范围。

我在GetIdentity中传递了app而不是ctx,然后在使用范围的GetIdentity中传递:

using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope()) {
    if (serviceScope.ServiceProvider.GetService<YourAppDbContext>() != null) 
    {
      var ctx = serviceScope.ServiceProvider.GetService<YourAppDbContext>();

      if (AnAuthenticateMethodHereMaybe(ctx, username, password)) {
        return Task.FromResult(new ClaimsIdentity(new 
GenericIdentity(username, "Token"), new Claim[] { }));
      }
    }
  }