ASP.NET Core 2.0-Authentifizierungs-Middleware

89

Mit Core 1.1 befolgte @ Blowdart den Rat und implementierte eine benutzerdefinierte Middleware:

https://stackoverflow.com/a/31465227/29821

Es hat so funktioniert:

  1. Middleware lief. Habe ein Token aus den Anforderungsheadern aufgenommen.
  2. Das Token wurde überprüft und, falls gültig, eine Identität (ClaimsIdentity) erstellt, die mehrere Ansprüche enthielt, die dann über HttpContext.User.AddIdentity () hinzugefügt wurden.
  3. In ConfigureServices using services.AddAuthorization habe ich eine Richtlinie hinzugefügt, die den Anspruch erfordert, der von der Middleware bereitgestellt wird.
  4. In den Controllern / Aktionen würde ich dann [Authorize (Roles = "eine Rolle, die die Middleware hinzugefügt hat") verwenden]

Dies funktioniert etwas mit 2.0, außer dass, wenn das Token nicht gültig ist (Schritt 2 oben) und der Anspruch nie hinzugefügt wird, "Es wurde kein Authentifizierungsschema angegeben und es wurde kein DefaultChallengeScheme gefunden."

Jetzt lese ich, dass sich die Authentifizierung in 2.0 geändert hat:

https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

Was ist der richtige Weg für mich, um dasselbe in ASP.NET Core 2.0 zu tun? Ich sehe kein Beispiel für eine wirklich benutzerdefinierte Authentifizierung.

pbz
quelle
Probieren Sie diesen Link aus, obwohl er 2 Schemata enthält, aber er würde Sie auf Authentifizierung aufmerksam machen wildermuth.com/2017/08/19/…
Mithun Pattankar
Könnten Sie Ihren Code hinzufügen, damit wir einen Blick darauf werfen können? Ich weiß, ich hatte Probleme mit JWT in Core 2.0 - war ein Fall von Verschieben im Startup
Webezine

Antworten:

192

Nach einem langen Tag, an dem versucht wurde, dieses Problem zu lösen, habe ich endlich herausgefunden, wie Microsoft benutzerdefinierte Authentifizierungshandler für das neue Single-Middleware-Setup in Core 2.0 erstellen soll.

Nachdem ich einige Dokumentationen zu MSDN durchgesehen hatte, fand ich eine Klasse namens AuthenticationHandler<TOption>, die die IAuthenticationHandlerSchnittstelle implementiert .

Von dort fand ich eine vollständige Codebasis mit den vorhandenen Authentifizierungsschemata unter https://github.com/aspnet/Security

In einem dieser Beispiele wird gezeigt, wie Microsoft das JwtBearer-Authentifizierungsschema implementiert. ( https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer )

Ich habe den größten Teil dieses Codes in einen neuen Ordner kopiert und alle Dinge gelöscht, die damit zu tun haben JwtBearer.

In der JwtBearerHandlerKlasse (die erweitert wird AuthenticationHandler<>) gibt es eine Überschreibung fürTask<AuthenticateResult> HandleAuthenticateAsync()

Ich habe unsere alte Middleware zum Einrichten von Ansprüchen über einen benutzerdefinierten Tokenserver hinzugefügt und hatte immer noch Probleme mit Berechtigungen. Ich habe nur ein 200 OKstatt eines ausgegeben, 401 Unauthorizedwenn ein Token ungültig war und keine Ansprüche eingerichtet wurden.

Mir wurde klar, dass ich überschrieben hatte, Task HandleChallengeAsync(AuthenticationProperties properties)was aus irgendeinem Grund zum Festlegen von Berechtigungen [Authorize(Roles="")]in einem Controller verwendet wird.

Nach dem Entfernen dieser Überschreibung hatte der Code funktioniert und erfolgreich eine ausgelöst, 401wenn die Berechtigungen nicht übereinstimmten.

Die wichtigste Erkenntnis daraus ist, dass Sie jetzt keine benutzerdefinierte Middleware verwenden können, sondern diese über implementieren AuthenticationHandler<>müssen und das DefaultAuthenticateSchemeund DefaultChallengeSchemebei der Verwendung festlegen müssen services.AddAuthentication(...).

Hier ist ein Beispiel, wie dies alles aussehen sollte:

Fügen Sie in Startup.cs / ConfigureServices () Folgendes hinzu:

services.AddAuthentication(options =>
{
    // the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...)
    options.DefaultAuthenticateScheme = "Custom Scheme";
    options.DefaultChallengeScheme = "Custom Scheme";
})
.AddCustomAuth(o => { });

Fügen Sie in Startup.cs / Configure () Folgendes hinzu:

app.UseAuthentication();

Erstellen Sie eine neue Datei CustomAuthExtensions.cs

public static class CustomAuthExtensions
{
    public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
    {
        return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
    }
}

Erstellen Sie eine neue Datei CustomAuthOptions.cs

public class CustomAuthOptions: AuthenticationSchemeOptions
{
    public CustomAuthOptions()
    {

    }
}

Erstellen Sie eine neue Datei CustomAuthHandler.cs

internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
    public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
        // store custom services here...
    }
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package
        return AuthenticateResult.NoResult();
    }
}
Zac
quelle
1
toller Beitrag, aber ich habe einige Probleme beim Kompilieren Ihres Codes. Die Typen CustomAuthOptions und AuthenticateResult fehlen. Könnten Sie diese posten?
Alexb
8
Sind Sie bereit, Ihre Schlussfolgerungen im Code eines Github-Repos mitzuteilen?
CSharper
2
Könnten Sie bitte erklären DefaultAuthenticateSchemeund DefaultChallengeScheme? Ich verstehe nicht, warum beide verwendet werden? und was ist der Unterschied zwischen ihnen.
Mohammed Noureldin
10
+1 für "Von dort aus habe ich eine vollständige Codebasis mit den vorhandenen Authentifizierungsschemata unter github.com/aspnet/Security gefunden ." Schauen Sie sich an, wie das ASP.NET-Team dies tut, während Sie dieser (wirklich hervorragenden) Antwort folgen. Hat irgendjemand von uns jemals gedacht, dass wir eines Tages Fragen zu MS-Code und -Praktiken stellen würden und die Antwort wäre: "Schauen Sie sich nur ihre Codebasis an?"
Marc L.
3
Für andere, die später hereinkommen, müssen Sie AuthExtensionsich im Microsoft.Extensions.DependencyInjectionNamespace befinden. Siehe dieses Beispiel: github.com/aspnet/Security/blob/rel/2.0.0/src/…
Garry Polley
4

Wie der Artikel, auf den Sie verweisen, zeigt, gibt es erhebliche Änderungen in der Identität von Core 1.x zu Core 2.0. Die wichtigste Änderung besteht darin, sich vom Middleware-Ansatz zu lösen und die Abhängigkeitsinjektion zum Konfigurieren benutzerdefinierter Dienste zu verwenden. Dies bietet viel mehr Flexibilität beim Anpassen der Identität für komplexere Implementierungen. Sie möchten sich also von dem oben erwähnten Middleware-Ansatz lösen und sich den Diensten zuwenden. Befolgen Sie die Migrationsschritte im Artikel, auf den verwiesen wird, um dieses Ziel zu erreichen. Ersetzen Sie zunächst app.UseIdentity durch app.UseAuthentication . UseIdentity wird abgeschrieben und in zukünftigen Versionen nicht mehr unterstützt. Ein vollständiges Beispiel zum Einfügen einer benutzerdefinierten Anspruchstransformation und zum Durchführen einer Autorisierung für den AnspruchDiesen Blog-Beitrag anzeigen .

Kevin Junghans
quelle
12
Gibt es ein Beispiel für die Verwendung mit einer WebAPI-App?
Alexb