Возврат HTTP 403 с использованием атрибута Authorize в ASP.Net Core

При использовании ASP.Net WebAPI у меня был атрибут custom Authorize, который я хотел бы использовать для возврата HTTP 403 или 401 в зависимости от ситуации. например если пользователь не аутентифицирован, верните a 401; если пользователь аутентифицирован, но не имеет соответствующих разрешений, верните 403. Подробнее см. здесь.

Теперь, в новом ядре ASP.Net, они не хотят, чтобы вы переопределяли атрибут Authorize, вместо этого предпочитая политический подход. Тем не менее, похоже, что Core MVC страдает от того же "just return 401 для всех ошибок auth", которые подходят его предшественникам.

Как переопределить фреймворк, чтобы получить нужное поведение?

Ответы

Ответ 1

После открытия проблема здесь, похоже, что это действительно должно работать... вроде.

В вашем Startup.Configure, если вы просто вызываете app.UseMvc() и не регистрируете какое-либо другое промежуточное программное обеспечение, вы получите 401 для любых связанных с auth ошибок (не аутентифицированных, аутентифицированных, но без разрешения).

Если, однако, вы зарегистрируете одно из поддерживающих его посредников по проверке подлинности, вы получите 401 для неаутентифицированных и 403 без каких-либо разрешений. Для меня я использовал JwtBearerMiddleware, который позволяет выполнять аутентификацию через JNON Web Token. Ключевой частью является установка опции AutomaticChallenge при создании промежуточного программного обеспечения:

в Startup.Configure:

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true
});
app.UseMvc();

AutomaticAuthenticate автоматически установит ClaimsPrincipal, чтобы вы могли получить доступ к User в контроллере. AutomaticChallenge позволяет промежуточному программному средству Auth изменять ответ при возникновении ошибок auth (в этом случае настройка 401 или 403 соответственно).

Если у вас есть ваша собственная схема аутентификации для реализации, вы бы наследовали от AuthenticationMiddleware и AuthenticationHandler, подобно тому, как работает реализация JWT.

Ответ 2

Я закончил работу с промежуточным программным обеспечением:

public class AuthorizeCorrectlyMiddleware
{
    readonly RequestDelegate next;

    public AuthorizeCorrectlyMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        await next(context);

        if (context.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
        {
            if (context.User.Identity.IsAuthenticated)
            {
                //the user is authenticated, yet we are returning a 401
                //let return a 403 instead
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            }
        }
    }
}

который должен быть зарегистрирован в Startup.Configure перед вызовом app.UseMvc().