Ответ 1
Итак, после долгого дня, пытаясь решить эту проблему, я, наконец, понял, как Microsoft хочет, чтобы мы сделали собственные обработчики проверки подлинности для своей новой установки однопользовательского ПО в основном 2.0.
После просмотра некоторой документации по MSDN я нашел класс под названием AuthenticationHandler<TOption>
, который реализует интерфейс IAuthenticationHandler
.
Оттуда я нашел целую базу кода с существующими схемами аутентификации, расположенными в https://github.com/aspnet/Security
Внутри одного из них он показывает, как Microsoft реализует схему аутентификации JwtBearer. (https://github.com/aspnet/Security/tree/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer)
Я скопировал большую часть этого кода в новую папку и очистил все, что связано с JwtBearer
.
В классе JwtBearerHandler
(который расширяет AuthenticationHandler<>
) существует переопределение для Task<AuthenticateResult> HandleAuthenticateAsync()
Я добавил в наше старое промежуточное ПО для настройки претензий через пользовательский сервер токенов и все еще сталкивался с некоторыми проблемами с разрешениями, просто выплевывая 200 OK
вместо 401 Unauthorized
, когда токен был недействительным, и никаких претензий не было настроен.
Я понял, что переопределил Task HandleChallengeAsync(AuthenticationProperties properties)
, который по какой-либо причине используется для установки разрешений через [Authorize(Roles="")]
в контроллере.
После удаления этого переопределения код работал и успешно выбрал 401
, когда разрешения не совпали.
Основной вывод из этого заключается в том, что теперь вы не можете использовать собственное промежуточное программное обеспечение, вы должны реализовать его с помощью AuthenticationHandler<>
, и при использовании services.AddAuthentication(...)
вы должны установить DefaultAuthenticateScheme
и DefaultChallengeScheme
.
Вот пример того, как все это должно выглядеть:
В Startup.cs/ConfigureServices() добавить:
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 => { });
В Startup.cs/Configure() добавить:
app.UseAuthentication();
Создайте новый файл 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);
}
}
Создайте новый файл CustomAuthOptions.cs
public class CustomAuthOptions: AuthenticationSchemeOptions
{
public CustomAuthOptions()
{
}
}
Создайте новый файл 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();
}
}