【问题标题】:.net core - How to return 403 on AuthorizationHandler?.net core - 如何在 AuthorizationHandler 上返回 403?
【发布时间】:2019-01-11 02:47:09
【问题描述】:

我实现了我的自定义 AuthorizationHandler。 在那我检查我用户可以解决并且是活跃的。

如果用户不活跃,那么我想返回 403 状态。

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidUserRequirement requirement)
{
    var userId = context.User.FindFirstValue( ClaimTypes.NameIdentifier );

    if (userId != null)
    {
        var user = await _userManager.GetUserAsync(userId);

        if (user != null)
        {
            _httpContextAccessor.HttpContext.AddCurrentUser(user);

            if (user.Active)
            {
                context.Succeed(requirement);
                return;
            }
            else
            {
                _log.LogWarning(string.Format("User ´{1}´ with id: ´{0} isn't active", userId, user.UserName), null);
            }
        }
        else
        {
            _log.LogWarning(string.Format("Can't find user with id: ´{0}´", userId), null);
        }
    } else
    {
        _log.LogWarning(string.Format("Can't get user id from token"), null);
    }

    context.Fail();

    var response = _httpContextAccessor.HttpContext.Response;
    response.StatusCode = 403;

}

但我收到了 401。你能帮帮我吗?

【问题讨论】:

  • 授权!= 身份验证。 401(未授权)是正确的状态码,而不是 403(禁止)。
  • 你是对的!我只尝试了 403 的返回,所以现在我可以通过身份验证来扩展这个方法。
  • HTTP 403 提供了与 HTTP 401 不同的错误案例; HTTP 401 在客户端未认证时返回,并暗示在经过有效认证后可能会返回成功的响应,而当客户端尽管提供了认证(例如已认证帐户的权限不足)仍不允许访问资源时,则返回 HTTP 403 . [维基百科]。 403 应该是“授权处理程序”中的状态码。

标签: api authentication asp.net-core .net-core jwt


【解决方案1】:

根据单一职责原则,我们不应该使用HandleRequirementAsync()方法来重定向响应,我们应该使用中间件或控制器来做到这一点。如果你把重定向逻辑放在HandleRequirementAsync(),如果你想在View page中使用呢?

您可以将与重定向相关的代码删除到其他地方(外部),现在您注入一个IAuthorizationService 来授权任何您喜欢的东西,甚至是基于资源的授权:

public class YourController : Controller{

    private readonly IAuthorizationService _authorizationService;
    public YourController(IAuthorizationService authorizationService)
    {
        this._authorizationService = authorizationService;
    }

    [Authorize("YYY")]
    public async Task<IActionResult> Index()
    {
        var resource  /* = ... */ ;
        var x = await this._authorizationService.AuthorizeAsync(User,resource , "UserNameActiveCheck");

        if (x.Succeeded)
        {
            return View();
        }
        else {
            return new StatusCodeResult(403);
        }
    }

}

【讨论】:

  • 我想为我所有的 api 函数这样做。似乎为每个方法都做一次比集中做一次要多得多。
【解决方案2】:

您能在函数结束时检查一下吗?在某些情况下,我在我的自定义中间件中使用它来将状态代码重写为 401,但在您的场景中也应该可以工作

var filterContext = context.Resource as AuthorizationFilterContext;
var response = filterContext?.HttpContext.Response;
response?.OnStarting(async () =>
{
    filterContext.HttpContext.Response.StatusCode = 403;
//await response.Body.WriteAsync(message, 0, message.Length); only when you want to pass a message
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2019-11-29
    • 2017-03-25
    • 2020-12-01
    • 1970-01-01
    相关资源
    最近更新 更多