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 IAuthenticationHandler
Schnittstelle 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 JwtBearerHandler
Klasse (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 OK
statt eines ausgegeben, 401 Unauthorized
wenn 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, 401
wenn 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 DefaultAuthenticateScheme
und DefaultChallengeScheme
bei 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();
}
}