【问题标题】:AuthorizationHandler<T> is not fired in AllowAnonymous controller method在 AllowAnonymous 控制器方法中未触发 AuthorizationHandler<T>
【发布时间】:2023-03-12 02:42:01
【问题描述】:

我正在使用 .Net Core 2.1 和 AngularJS 制作应用程序。 在我的 .Net Core 应用程序中,有一些方法允许经过身份验证和未经身份验证的用户访问。

这是我获取个人资料的方法

    /// <summary>
    ///     Find personal profile.
    /// </summary>
    /// <param name="id">Id of user. 0 for the request sender profile</param>
    /// <returns></returns>
    [HttpGet("personal-profile/{id}")]
    [AllowAnonymous]
    public async Task<IActionResult> FindProfile([FromRoute] int? id)
    {
        // Get requester identity.
        var profile = IdentityService.GetProfile(HttpContext);

        // Search for accounts.
        var accounts = UnitOfWork.Accounts.Search();

        if (id == null || id < 1)
        {
            if (profile != null)
                accounts = accounts.Where(x => x.Id == profile.Id);
            else
                return Ok();
        }
        else
            accounts = accounts.Where(x => x.Id == id);

        // Only search for active account.
        accounts = accounts.Where(x => x.Status == AccountStatus.Available);

        // Find the first account in system.
        var account = await accounts.FirstOrDefaultAsync();
        return Ok(account);
    }

这是我的 AuthorizationHandler 类。

    /// <summary>
    ///     Handle requirement asychronously.
    /// </summary>
    /// <param name="context"></param>
    /// <param name="requirement"></param>
    /// <returns></returns>
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
        SolidAccountRequirement requirement)
    {
        // Convert authorization filter context into authorization filter context.
        var authorizationFilterContext = (AuthorizationFilterContext) context.Resource;

        //var httpContext = authorizationFilterContext.HttpContext;
        var httpContext = _httpContextAccessor.HttpContext;

        // Find claim identity attached to principal.
        var claimIdentity = (ClaimsIdentity) httpContext.User.Identity;

        // Find email from claims list.
        var email =
            claimIdentity.Claims.Where(x => x.Type.Equals(ClaimTypes.Email))
                .Select(x => x.Value)
                .FirstOrDefault();

        // Email is invalid.
        if (string.IsNullOrEmpty(email))
        {
            context.Fail();
            return;
        }

        // Find accounts based on conditions.
        var accounts = _unitOfWork.Accounts.Search();
        accounts = accounts.Where(x =>
            x.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase) && x.Status == AccountStatus.Available);

        // Find the first matched account in the system.
        var account = await accounts.FirstOrDefaultAsync();

        // Account is not found.
        if (account == null)
            return;

        // Initiate claim identity with newer information from database.
        var claimsIdentity = new ClaimsIdentity();
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Email, email));
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, account.Nickname));
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, Enum.GetName(typeof(AccountRole), account.Role)));
        claimsIdentity.AddClaim(new Claim(ClaimTypes.Authentication,
            Enum.GetName(typeof(AccountStatus), account.Status)));

        // Update claim identity.
        _identityService.SetProfile(httpContext, account);
        context.Succeed(requirement);
    }

这就是我正在做的。

  • 在AuthorizationHandler中,检查请求身份(由JWT Bearer中间件解析)
  • 查询数据库查找用户信息。
  • 找到用户后,用户信息将附加到httpContext.Items[ClaimTypes.Actor]

这就是我的代码中发生的情况: - 使用邮递员向api/user/personal-profile/0 发送请求以获取请求发件人资料。 - 在FindProfile中,profile变量为空,而不是用户信息,这意味着AuthorizationHandler没有被触发。

如果我从 FindProfile 方法中删除 [AllowAnonymous] 属性,一切正常。

请查看我在下面附上的那两张图片以获取更多信息:

我的问题是: 我们可以使用 AllowAnonymous 方法触发AuthorizationHandler。在我的系统中,这两种用户都可以使用一些 API。

  • 如果用户是管理员,会返回一些额外的信息。
  • 如果用户是普通用户,返回的信息很少。

谢谢

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc asp.net-core-2.0 asp.net-core-webapi asp.net-authorization


    【解决方案1】:

    &gt; Can we make AuthorizationHandler be triggered with AllowAnonymous method?

    不,你不能。 [AllowAnonymous] 绕过所有授权语句。如果你有兴趣,this is the corresponding code 在AuthorizeFilter.OnAuthorizationAsync 实现。

    if (context.Filters.Any(item => item is IAllowAnonymousFilter))
    {
       return;
    }
    

    考虑删除AllowAnonymous 并添加一些自定义逻辑。例如,您可以创建自己的 MVC 过滤器。比方说:

    public class MyAllowAnonymous : ActionFilterAttribute {}
    

    然后在AuthorizationHandler 中检查authorizationFilterContext.Filters 集合是否有这个过滤器。如果是,则返回context.Succeed(requirement);。

    • 考虑使用另一个 IAuthorizationRequirement 创建一个单独的 AuthorizationHandler 实现。

    • 您可以直接通过authorizationFilterContext.ActionDescriptor获取路由名称,而不是过滤器检查,并决定是否允许匿名访问。但是你的 AuthorizationHandler 应该知道路由列表。

    【讨论】:

    • 谢谢,我已经使用 AuthorizationHandler 实现了我的目标并成功了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    相关资源
    最近更新 更多