【问题标题】:Cannot access HttpContextAccessor User Claims on OnActionExecuting无法访问 OnActionExecuting 上的 HttpContextAccessor 用户声明
【发布时间】:2021-04-15 04:52:03
【问题描述】:

我正在使用带有 JWT 的 .net 核心进行身份验证。我正在尝试在我的自定义属性中访问来自HttpContextAccessor 的用户声明。在应用程序中,我有一个 UserService.cs(下面的代码),我可以在其中执行此操作。但是在我的自定义属性中的OnActionExecuting 上,声明是一个空错误。即使我从我的用户服务中调用该函数,声明也不存在。

我的最终目标是获取用户的 id 以检查用户是否具有管理员访问权限。我不想在令牌上存储管理员访问状态。

UserService.cs


    public AuthenticatedUserClaims AuthenticatedUser()
            {
                var userClaims = new AuthenticatedUserClaims();
                var claims = _contextAccessor.HttpContext.User.Claims;
                var enumerable = claims as Claim[] ?? claims.ToArray();
                var userId = enumerable.SingleOrDefault(x => x.Type == "UserId")?.Value;
                userClaims.UserName = enumerable.SingleOrDefault(x => x.Type == "UserName")?.Value;
                userClaims.FullName = enumerable.SingleOrDefault(x => x.Type == "FullName")?.Value;
                if (userId != null && !string.IsNullOrEmpty(userId)) userClaims.UserId = int.Parse(userId);
    
                return userClaims;
            }

我的自定义属性

        [AttributeUsage(AttributeTargets.Class| AttributeTargets.Method)]
        public class PermissionsRequiredAttribute: ActionFilterAttribute
        {
            private readonly IHttpContextAccessor _contextAccessor;
    
            public PermissionsRequiredAttribute(IHttpContextAccessor contextAccessor)
            {
                _contextAccessor = contextAccessor;
            }
            public override void OnActionExecuting(ActionExecutingContext context)
            {
                var claims = _contextAccessor.HttpContext.User.Claims;
                var claimsList = claims as Claim[] ?? claims.ToArray();
                // claimsList = Claims[0]??
                // context.Result = new UnauthorizedResult();
                base.OnActionExecuting(context);
            }
            
        }

属性使用

     [HttpGet("{id}")]
     [ServiceFilter(typeof(PermissionsRequiredAttribute))]
     public async Task<ActionResult<Beneficiary>> GetBeneficiary([FromRoute] int id) { //... }

Startup.cs 上的配置服务

    services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
    services.AddScoped<PermissionsRequiredAttribute>();

提前致谢:)

【问题讨论】:

    标签: .net-core jwt


    【解决方案1】:

    我发现了一个基于this answer 的“hackaround”,但我仍然不知道为什么我的用户 HttpContext 是空的。

    
        [AttributeUsage(AttributeTargets.Class| AttributeTargets.Method)]
        public class PermissionsRequiredAttribute: ActionFilterAttribute
        {
            private readonly IUser _user;
    
            public PermissionsRequiredAttribute(IUser user)
            {
                _user = user;
            }
    
            public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
            {
                bool headers = context.HttpContext.Request.Headers.TryGetValue("Authorization", out var tokens);
                string token = tokens.FirstOrDefault()?.Split(" ")[1];
                if (string.IsNullOrEmpty(token)) 
                    context.Result = new UnauthorizedResult();
                var handler = new JwtSecurityTokenHandler();
                JwtSecurityToken securityToken = (JwtSecurityToken) handler.ReadToken(token);
                IEnumerable<Claim> claims = securityToken.Payload.Claims;
                string userId = claims.SingleOrDefault(c => c.Type == "UserId")?.Value;
                if (!string.IsNullOrEmpty(userId))
                    context.Result = new UnauthorizedResult();
                var currentUser = await _user.GetUser(int.Parse(userId ?? throw new UnauthorizedAccessException()));
                if (!currentUser.isAdmin)
                    context.Result = new UnauthorizedResult();
                await base.OnActionExecutionAsync(context, next);
            }
    
        }
    
    

    编辑:2021 年 16 月 10 日

    我找到了一个令我满意的解决方案,看来我只需要将Startup.cs 中的行添加到ConfigureServices(IServiceCollection services)

     services.AddHttpContextAccessor();
    

    现在下面的行有值Claims

    var claims = _contextAccessor.HttpContext.User.Claims;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-22
      • 2020-01-15
      相关资源
      最近更新 更多