Я пытаюсь создать собственный AuthenticationHandler в ASP.Net Core 2. Следуя таким темам, как ПО промежуточного слоя для проверки подлинности ASP.NET Core 2.0 и Почему схема аутентификации Asp.Net Core обязательна, я создал определенные классы. Регистрация происходит так:
services.AddAuthentication(
options =>
{
options.DefaultScheme = Constants.NoOpSchema;
options.DefaultAuthenticateScheme = Constants.NoOpSchema;
options.DefaultChallengeScheme = Constants.NoOpSchema;
options.DefaultSignInScheme = Constants.NoOpSchema;
options.DefaultSignOutScheme = Constants.NoOpSchema;
options.DefaultForbidScheme = Constants.NoOpSchema;
}
).AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
Все работает, если конкретные контроллеры явно задают схему:
[Authorize(AuthenticationSchemes= Constants.NoOpSchema)]
[Route("api/[controller]")]
public class IndividualsController : Controller
Но мне бы не хотелось устанавливать схему, так как она должна добавляться динамически. Как только я удалю свойство схемы, вот так:
[Authorize]
[Route("api/[controller]")]
public class IndividualsController : Controller
Больше не работает.
Я бы надеялся, что настройка DefaultScheme Properties сделает эту работу. Что интересно, я не нашел особого обсуждения этой темы. Я здесь что-то делаю не так или мой ожидаемый результат неверен?
Обновлено: Спасибо за вопросы, это мне очень помогло. Похоже, отображение DefaultScheme используется промежуточным программным обеспечением аутентификации, которое я использовал только тогда, когда CustomAuthHandler не был на месте. Поэтому мне всегда приходилось добавлять AuthenticationMiddleware.
Edit2: К сожалению, это все еще не работает. Чтобы немного улучшить мой вопрос: я добавляю промежуточное ПО как обычно:
app.UseAuthentication();
app.UseMvc();
Теперь я попадаю в свой обработчик, который выглядит так:
public class NoOpAuthHandler : AuthenticationHandler<NoOpAuthOptions>
{
public const string NoOpSchema = "NoOp";
public NoOpAuthHandler(IOptionsMonitor<NoOpAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync() => Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, NoOpSchema)));
}
Но даже если я всегда возвращаю успех, я получаю 401. Я думаю, что мне нужно копнуть глубже и как бы установить некоторые утверждения, но, к сожалению, обработчики от Microsoft довольно сложно анализировать, поскольку они содержат много кода.
какая ошибка возникает при удалении AuthenticationSchemes
?
Что делает CustomAuthHandler?
Я полагаю, вы знаете, но вы можете унаследовать атрибут авторизации, чтобы избежать AuthenticationSchemes = Constants.NoOpSchema
Убедитесь, что у вас есть промежуточное ПО для аутентификации в конвейере и поместите его перед MVC.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
///
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
///
}
ОБНОВИТЬ
попробуйте использовать этот код в методе HandleAuthenticateAsync
.
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
List<Claim> claims = new List<Claim>();
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, Scheme.Name);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
AuthenticationTicket authenticationTicket = new AuthenticationTicket(claimsPrincipal, Scheme.Name);
return AuthenticateResult.Success(authenticationTicket);
}
Еще одно замечание: в .NET Core 3/5 убедитесь, что у вас есть app.UseAuthentication
ДО app.UseAuthorization()
. Идут 2 часа моего дня :)
Ответ ASP.Net Core 2
Вы должны установить политику авторизации по умолчанию, привязанную к вашей схеме аутентификации:
services.AddAuthorization(options => {
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(Constants.NoOpSchema)
.RequireAuthenticatedUser()
.Build();
});
Ответ ASP.Net Core 3
В ASP.Net Core 3 все, по-видимому, немного изменилось, поэтому вам нужно создать метод расширения для добавления обработчика аутентификации:
public static class NoOpAuthExtensions
{
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder)
=> builder.AddNoOpAuth(NoOpAuthHandler.NoOpSchema, _ => { });
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, Action<NoOpAuthOptions> configureOptions)
=> builder.AddNoOpAuth(NoOpAuthHandler.NoOpSchema, configureOptions);
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, string authenticationScheme, Action<NoOpAuthOptions> configureOptions)
=> builder.AddNoOpAuth(authenticationScheme, null, configureOptions);
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<NoOpAuthOptions> configureOptions)
{
return builder.AddScheme<NoOpAuthOptions, NoOpAuthHandler>(authenticationScheme, displayName, configureOptions);
}
}
И используйте его в своем методе ConfigureServices следующим образом:
services
.AddAuthentication(NoOpAuthHandler.NoOpSchema)
.AddNoOpAuth();
Это сработало для меня. Я не уверен, для чего на самом деле предназначен DefaultAuthenticateScheme
, но он не для установки схемы [Авторизация] по умолчанию.
попробуй это.
services.AddAuthentication(
options =>
{
options.DefaultAuthenticateScheme = "Cookie"
options.DefaultChallengeScheme = Constants.NoOpSchema;
options.DefaultSignInScheme = "Cookie";
}
)
.AddCookie("Cookie")
.AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
Я страдаю от этого часами, в моем случае проблема заключалась в классе AuthenticationMiddleware по умолчанию. Точнее; Если вы установите ClaimsPrincipal в настраиваемом промежуточном программном обеспечении в конвейере запросов, как показано ниже:
HttpContext.context.User = new ClaimsPrincipal(identity);
это переопределит ваши настройки конфигурации аутентификации по умолчанию,
Что я сделал, чтобы решить; удалите пользовательское промежуточное ПО и добавьте app.UseAuthentication();
в раздел Configure в Startup.cs, а атрибут Authroize проверяет все, что установлено в разделе config по умолчанию;
Вот мой;
services.AddAuthentication(x =>
{
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateLifetime = true,
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
});
в .NET Core 3.1 мне пришлось вручную добавить [Authorize(AuthenticationSchemes = "Bearer")]
вместо простого [Authorize]
в конечные точки, чтобы аутентификация работала так, как я ожидал. Следующее изменение конфигурации решило проблему:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Bearer";
})
Вы добавили
app.UseAuthentication()
в свой конвейер промежуточного программного обеспечения?