最近、.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
私の質問は次のとおりです。
はい、データベースにアクセスできます! 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
デリゲートを記述しようとしました。もちろん、あなたは私のコードを捨てて、より良いことをするのも自由です。 :)
.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から解決されます。
受け入れられた回答はスコープサービスでは機能しません( 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
メソッドの引数でそれを渡します
他のレベルでは間違っているかもしれませんが、解決策はスコープを作成することです。
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[] { }));
}
}
}