#asp.net #.net #asp.net-web-api #asp.net-core #.net-core
#asp.net #.net #asp.net-web-api #asp.net-core #.net-core
Вопрос:
Я провел последние несколько дней, играя с аутентификацией для своей службы в ASP.NET Ядро. Мое приложение имеет простую систему токенов аутентификации. Ожидается, что в запросе содержится файл cookie, я беру этот файл cookie и отправляю запрос на свой сервер аутентификации. Сервер аутентификации возвращает мне права пользователя. Если файл cookie не существует или запрос аутентификации возвращается с ошибкой, приложение должно выдать 401. В случае успеха он перейдет к следующей части конвейера и проверит авторизацию на правах.
Я настроил свое промежуточное программное обеспечение аутентификации, как и следовало ожидать, — наследование от AuthenticationHandler, AuthenticationMiddleware и т. Д. Мой пользовательский обработчик аутентификации наследуется от Authenticationhandler и перезаписывает HandleAuthenticateAsync() . Этот метод использует предоставленный пользователем файл cookie для получения пользовательских данных, создания моего ClaimsPrincipal и либо возвращает AuthenticateResult .Успех или ошибка аутентификации.
Когда AuthenticationResult.Сбой возвращает, я полагал, что приложение завершит работу, но мое приложение все равно перейдет к следующей части конвейера (app.UseMvc()), когда я думал, что оно вернет ошибку 401.
Мой Startup.cs выглядит следующим образом.
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCustomAuthentication(new CustomAuthenticationOptions()
{
AutomaticChallenge = true,
AutomaticAuthenticate = true
});
app.UseMvc();
}
}
Это приведет к сбою аутентификации, я увижу это в выходных данных, но тогда UseMvc все равно будет выполняться. Только после того, как я сделал это со службами, он завершит работу, но с ошибкой авторизации, а не с ошибкой аутентификации, которая должна была быть отмечена.
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
Так ли это должно быть настроено? При сбое аутентификации не следует ли завершить работу конвейера?
Ответ №1:
При сбое аутентификации не следует ли завершить работу конвейера?
Предположим, у вас есть другое промежуточное программное обеспечение для проверки подлинности:
app.UseCustomAuthentication(new CustomAuthenticationOptions()
{
AutomaticChallenge = true,
AutomaticAuthenticate = true
});
app.UseOtherAuthentication(new OtherAuthenticationOptions()
{
AutomaticChallenge = true,
AutomaticAuthenticate = true
});
Если конвейер завершается при сбое первой проверки подлинности, другое промежуточное программное обеспечение аутентификации никогда не запускается. Это было бы менее расширяемым.
Другой момент, предположим, вы хотите разрешить какое-либо действие для анонимного запроса с использованием AllowAnonymous
атрибута. Как вы разрешаете?
Даже если промежуточное программное обеспечение аутентификации завершается с ошибкой, без вызова HttpContext.Authentication.ChallengeAsync()
или использования Authorize
атрибута сервер не отвечает 401, 403 или 302.
Насколько я знаю, это ожидаемое поведение, и встроенная проверка подлинности cookie работает так же. Если вы хотите сначала принудительно аутентифицировать пользователя, вам нужно добавить его глобально (как вы это делаете) или использовать Authorize
атрибут поверх контроллера.