wake-up-neo.com

Kann ich während des Startvorgangs in ASP.NET Core auf eine Datenbank zugreifen?

Ich habe kürzlich an einer .NET Core-Web-API gearbeitet. Ich habe gerade versucht, mich mit JWT zu authentifizieren, indem ich der Anleitung unter https://stormpath.com/blog/token-authentication-asp-net-core gefolgt bin.

Alles lief gut, bis ich den fest codierten Benutzernamen und die Kennwörter in der Methode GetIdentity durch eine DB-Abfrage ersetzen musste und feststellte, dass ich nicht weiß, wie ich von dieser Datei aus auf die DB zugreifen soll!

Die Methode, auf die ich mich beziehe, wird in dem folgenden Link in Zeile 70 gezeigt. https://github.com/nbarbettini/SimpleTokenProvider/blob/master/test/SimpleTokenProvider.Test/Startup.Auth.cs

Meine Fragen sind wie folgt.

  1. Kann ich hier auf die Datenbank zugreifen? Wenn das so ist, wie?
  2. Sollte dies der Ort sein, an dem sich die GetIdentity-Methode befindet, oder gibt es einen besseren Weg?
13
Top Rat

Ja, Sie können auf die Datenbank zugreifen! Code, der in der Configure-Methode ausgeführt wird, kann auf alle Dienste zugreifen, die in der ConfigureServices-Methode hinzugefügt werden, einschließlich Dingen wie Datenbankkontexten.

Wenn Sie beispielsweise einen einfachen Entity Framework-Kontext haben:

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; }
    }
}

Und Sie fügen es in ConfigureServices hinzu:

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

Dann können Sie darauf zugreifen, wenn Sie die Middleware einrichten:

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)
});

Und schreibe die GetIdentity Methode ein wenig um:

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
}

Ich bin der Autor des Originalmusters. Sorry, es war anfangs nicht klar! Ich habe versucht, den IdentityResolver-Delegaten so zu schreiben, dass es Ihnen leicht fällt, Ihre eigenen Funktionen bereitzustellen - beispielsweise die Integration in Ihre eigene Datenbank (wie oben) oder die Anbindung an ASP.NET Core Identity. Natürlich können Sie meinen Code wegwerfen und auch etwas Besseres tun. :)

13
Nate Barbettini

Übergeben Sie in .NET CORE 2.1 einfach den Kontext als Argument an die Configure-Methode:

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

Die akzeptierte Antwort funktioniert nicht für Scope-Services ( Scope Services werden pro Anforderung erstellt, wenn Sie Entity Framework verwenden und den Kontext mit AddDbContext hinzufügen, dann dies ist der Fall ).

Sie können bereichsabhängige Dienste beim Start wie folgt verwenden ( 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>();
    }
}

oder übergeben Sie es im Argument der Configure-Methode, wie in der Antwort von juanora gezeigt

3
Florian Moser

Ich könnte auf einer anderen Ebene falsch sein, aber die Lösung, die ich gefunden habe, ist das Erstellen eines Bereichs.

Ich habe die App statt des ctx in GetIdentity und dann in GetIdentity mit einem Bereich übergeben: 

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.