簡體   English   中英

我可以在ASP.NET Core啟動期間訪問數據庫嗎?

[英]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

我的問題如下。

  1. 我可以在這里訪問數據庫嗎? 如果是這樣的話?
  2. 這應該是GetIdentity方法的位置,還是有更好的方法?

是的,您可以訪問數據庫! ,在運行的代碼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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM