代码之家  ›  专栏  ›  技术社区  ›  Jeremy Holovacs

ASP。NET Core授权策略:无法进入处理程序?

  •  7
  • Jeremy Holovacs  · 技术社区  · 7 年前

    我在中设置了基于JWT的声明身份验证/授权。NET核心应用程序,它按预期进行身份验证,但我的策略实施并没有按预期进行。

    我的需求实现和处理程序设置如下:

    public class ImpersonationRequirement : IAuthorizationRequirement
    {
    }
    
    public class ImpersonationHandler : AuthorizationHandler<ImpersonationRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
            ImpersonationRequirement requirement)
        {
            if (context.User.CanImpersonate()) context.Succeed(requirement);
    
            return Task.CompletedTask;
        }
    }
    

    我的助手设置如下:

    public static bool CanImpersonate(
        this ClaimsPrincipal principal)
    {
        var val = principal?.FindFirst(MyClaimTypes.CAN_IMPERSONATE)?.Value;
        return bool.TryParse(val, out var value) && value;
    }
    
    public class MyClaimTypes
    {
        /// <summary>
        /// Boolean value indicating this user is authorized to impersonate other customer accounts.
        /// </summary>
        public const string CAN_IMPERSONATE = "cim";
    
        ...
    
        /// <summary>
        /// Actual name of the user impersonating the current user.
        /// </summary>
        public const string IMPERSONATING_USER = "imp";
    }
    

    。。。从我的 Startup.cs ,我定义了策略:

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Impersonator", policy => policy.Requirements.Add(new ImpersonationRequirement()));
    });
    

    。。。在我的控制器上写着:

    [Produces("application/json")]
    [Authorize(Policy = "Impersonator")]
    public class ImpersonationController : Controller
    {
        private readonly ILogger _logger;
        private readonly ITokenManagementService _tokenManagementService;
        private readonly UserManager<MyUser> _userManager;
    
        public ImpersonationController(ITokenManagementService tokenManagementService, ILoggerFactory loggerFactory, UserManager<MyUser> userManager)
        {
            _tokenManagementService = tokenManagementService;
            _userManager = userManager;
            _logger = loggerFactory.CreateLogger<ImpersonationController>();
        }
    
        [HttpPost]
        [Route("~/api/impersonation/token")]
        [ProducesResponseType(typeof(AuthenticationResponse), 200)]
        [ProducesResponseType(typeof(Exception), 500)]
        public async Task<IActionResult> Impersonate([FromBody] string userNameToImpersonate)
        {
            try
            {
                var impersonated = await _userManager.FindByNameAsync(userNameToImpersonate);
                if (impersonated == null) throw new EntityNotFoundException($"Unable to find user '{userNameToImpersonate}' in the data store.");
                var actualUserId = User.UserId();
                var token = await _tokenManagementService.GenerateJwt(impersonated.Id, actualUserId);
                var refresh = await _tokenManagementService.GenerateRefreshToken(impersonated.Id, actualUserId);
                var response = new AuthenticationResponse {AuthenticationToken = token, RefreshToken = refresh};
                return Ok(response);
            }
            catch (Exception ex)
            {
                return new OopsResult(ex);
            }
        }
    }
    

    如果我用 AuthorizeAttribute 注释掉后,我可以查看用户的声明,并且“cim:true”在声明枚举中,但如果我使用 授权属性 启用后,我得到一个403禁止的错误。

    我试着在 ImpersonationHandler :

    if (context.User.CanImpersonate()) context.Succeed(requirement);
    

    。。。但是调试器从来没有停在这里,所以我不知道问题出在哪里。有人能告诉我我做错了什么吗?

    1 回复  |  直到 7 年前
        1
  •  15
  •   Evk    7 年前

    看来你忘记注册了 ImpersonationHandler 在DI容器中(确实很容易忘记):

    services.AddSingleton<IAuthorizationHandler, ImpersonationHandler>();
    

    Asp。net从容器中解析所有此类处理程序,并尝试匹配特定需求。由于未注册此类处理程序,因此未设置任何内容 context.Succeed 整个授权失败。