[英]Can I access a database during startup in ASP.NET Core?
我最近一直在研究.NET Core Web API。 我剛剛通過https://stormpath.com/blog/token-authentication-asp-net-core上的指南嘗試使用JWT進行身份驗證。
一切順利,直到我不得不用數據庫查詢GetIdentity
方法中的硬編碼用戶名和密碼,並意識到我不知道如何從這個文件中訪問數據庫!
我所指的方法顯示在第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
}
我是原始樣本的作者。 對不起,最初還不清楚! 我試圖以一種易於提供自己的功能的方式編寫IdentityResolver
委托 - 比如與您自己的數據庫集成(如上所述),或者將其掛鈎到ASP.NET Core Identity。 當然,您可以隨意丟棄我的代碼並做更好的事情。 :)
在.NET CORE 2.1上,只需將上下文作為參數傳遞給Configure方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, YourDbContext context)
{
//do whatever you want with the context here...
}
接受的答案不適用於作用域服務(每個請求都會創建作用域服務,如果您使用的是Entity Framework並使用AddDbContext
添加上下文,則情況就是這樣 )。
您可以在啟動時使用作用域服務,如下所示( 源 ):
// 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的答案所示
我可能在其他一些層面上錯了,但我找到的解決方案是創建一個范圍。
我在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[] { }));
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.