web-dev-qa-db-ja.com

ASP.NET Coreで起動中にデータベースにアクセスできますか?

最近、.NET Core Web APIに取り組んでいます。 https://stormpath.com/blog/token-authentication-asp-net-core のガイドに従って、JWTを使用して認証を試みました。

GetIdentityメソッドのハードコードされたユーザー名とパスワードをDBクエリに置き換える必要があり、このファイル内からDBにアクセスする方法がわからないことに気づくまで、すべてうまくいきました。

私が参照しているメソッドは、以下のリンクの70行目に示されています。 https://github.com/nbarbettini/SimpleTokenProvider/blob/master/test/SimpleTokenProvider.Test/Startup.Auth.cs

私の質問は次のとおりです。

  1. ここでデータベースにアクセスできますか?もしそうなら?
  2. これはGetIdentityメソッドがあるべきですか、それとももっと良い方法がありますか?
18
Top Rat

はい、データベースにアクセスできます! Configureメソッドで実行されるコードは、ConfigureServicesメソッドで追加されたサービス(データベースコンテキストなど)にアクセスできます。

たとえば、単純なEntity Frameworkコンテキストがある場合:

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
}

私は元のサンプルの作者です。最初ははっきりしていませんでした! (上記のように)独自のデータベースと統合したり、ASP.NET Core Identityに接続したりするなど、独自の機能を簡単に提供できるようにIdentityResolverデリゲートを記述しようとしました。もちろん、あなたは私のコードを捨てて、より良いことをするのも自由です。 :)

16
Nate Barbettini

.NET CORE 2.1では、コンテキストを引数としてConfigureメソッドに渡します。

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

サービスコンテナーにサービスを追加すると、アプリ内およびConfigureメソッドでサービスを利用できるようになります。サービスは、依存性注入またはApplicationServicesから解決されます。

10
juanora

受け入れられた回答はスコープサービスでは機能しません( scoped Entity Frameworkを使用していて、AddDbContextでコンテキストを追加している場合、サービスはリクエストごとに作成されます これはケースです )。

スコープサービスは、起動時に次のように使用できます( 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>();
    }
}

または、juanoraの回答に示されているように、Configureメソッドの引数でそれを渡します

7
Florian Moser

他のレベルでは間違っているかもしれませんが、解決策はスコープを作成することです。

GetIdentityで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[] { }));
      }
    }
  }
0
Nick G.