У меня есть обработчик авторизации на основе настраиваемой политики, как определено ниже. Аутентификация выполняется до того, как пользователь попадет в это приложение, поэтому мне нужна только авторизация. Я получаю сообщение об ошибке:
No authenticationScheme was specified, and there was no DefaultForbidScheme.
Если проверка авторизации прошла успешно, я не получаю сообщение об ошибке и все в порядке. Эта ошибка возникает только в случае сбоя проверки авторизации. Я ожидал, что 401 вернется в случае неудачи.
public class EasRequirement : IAuthorizationRequirement
{
public EasRequirement(string easBaseAddress, string applicationName, bool bypassAuthorization)
{
_client = GetConfiguredClient(easBaseAddress);
_applicationName = applicationName;
_bypassAuthorization = bypassAuthorization;
}
public async Task<bool> IsAuthorized(ActionContext actionContext)
{
...
}
}
public class EasHandler : AuthorizationHandler<EasRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EasRequirement requirement)
{
var mvcContext = context.Resource as ActionContext;
bool isAuthorized;
try
{
isAuthorized = requirement.IsAuthorized(mvcContext).Result;
}
catch (Exception)
{
// TODO: log the error?
isAuthorized = false;
}
if (isAuthorized)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
context.Fail();
return Task.FromResult(0);
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var easBaseAddress = Configuration.GetSection("EasBaseAddress").Value;
var applicationName = Configuration.GetSection("ApplicationName").Value;
var bypassAuthorization = bool.Parse(Configuration.GetSection("BypassEasAuthorization").Value);
var policy = new AuthorizationPolicyBuilder()
.AddRequirements(new EasRequirement(easBaseAddress, applicationName, bypassAuthorization))
.Build();
services.AddAuthorization(options =>
{
options.AddPolicy("EAS", policy);
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSingleton<IAuthorizationHandler, EasHandler>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
}





Авторизация и проверка подлинности тесно связаны в ASP.NET Core. Если авторизация не удалась, это будет передано обработчику аутентификации для обработки ошибки авторизации.
Таким образом, даже если вам не нужна фактическая аутентификация для идентификации пользователей, вам все равно потребуется настроить некоторую схему аутентификации, которая способна обрабатывать запрещенные и оспаривать результаты (403 и 401).
Для этого вам нужно вызвать в AddAuthentication() и настроить схему запрета / вызова по умолчанию:
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = "scheme name";
// you can also skip this to make the challenge scheme handle the forbid as well
options.DefaultForbidScheme = "scheme name";
// of course you also need to register that scheme, e.g. using
options.AddScheme<MySchemeHandler>("scheme name", "scheme display name");
});
MySchemeHandler должен реализовывать IAuthenticationHandler, и в вашем случае вам особенно необходимо реализовать ChallengeAsync и ForbidAsync:
public class MySchemeHandler : IAuthenticationHandler
{
private HttpContext _context;
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{
_context = context;
return Task.CompletedTask;
}
public Task<AuthenticateResult> AuthenticateAsync()
=> Task.FromResult(AuthenticateResult.NoResult());
public Task ChallengeAsync(AuthenticationProperties properties)
{
// do something
}
public Task ForbidAsync(AuthenticationProperties properties)
{
// do something
}
}
@ChristophAdamakis Нет, так связаны аутентификация и авторизация. В случае сбоя авторизации схема проверки подлинности должна обработать этот сбой. - Что бы вы хотели там делать вместо этого? Что-то должно произойти.
@ajamrozek Запрос учетных данных, как во всплывающем окне браузера, которое запрашивает ваш логин? Или просто перенаправление на какую-то форму входа? Первое невозможно, а второе явно предотвращается вашей собственной схемой аутентификации. Может быть, вам стоит задать новый вопрос, касающийся того, что именно вы делаете. Не стесняйтесь размещать ссылку на вопрос здесь, и я посмотрю.
«Не должно быть». Вызов принят;) Оказывается, у меня были некоторые устаревшие вещи, которые включали WindowsAuth в launchsettings.json. Вынул это, и больше нет подсказки. В остальном этот ответ действительно помог мне.
@ajamrozek Windows auth там имеет смысл - рад, что вы в этом разобрались :)
А если кому интересно, как должно выглядеть «сделать что-нибудь», обратитесь к stackoverflow.com/a/54587054/106688
Для IIS / IIS Express можно просто добавить эту строку вместо всего вышеперечисленного в принятый ответ, чтобы получить соответствующий ожидаемый ответ 403;
services.AddAuthentication(IISDefaults.AuthenticationScheme);
Есть ли способ предотвратить описанное вами поведение по умолчанию? «Если авторизация не удалась, это будет передано обработчику аутентификации для обработки ошибки авторизации»