将授权策略应用于整个控制器时忽略使用属性

Consume Attribute Ignored when Authorize Policy is applied to entire controller

我们一直在进行一些安全测试并发现一个问题,如果 posted 的内容类型不正确,则会返回 400 而不是 415。

现在只有当我将我的授权属性应用到整个控制器,然后在 post 操作上设置我的消耗属性时,才会发生这种情况。当 Authorize Attribute 与 Consumes Attribute 一起仅应用于一个动作时,这就可以正常工作了。

这个有效:Returns 415

public class MyController : Controller
{
        [HttpPost]
        [Authorize(Policy = "MyPolicy")]
        [Consumes("application/x-www-form-urlencoded")]
        public async Task<IActionResult> APostActrion(MyModel model)
        {
            return View();
        }

}

这不是:Returns 400

[Authorize(Policy = "MyPolicy")]
public class MyController : Controller
    {
            [HttpPost]                
            [Consumes("application/x-www-form-urlencoded")]
            public async Task<IActionResult> APostActrion(MyModel model)
            {
                return View();
            }
    
    }

编辑

这是我的政策示例

options.AddPolicy("MyPolicy", b =>
            {
                b.RequireAuthenticatedUser();
                b.RequireClaim(ClaimTypes.Role, "MyRole");
                b.Requirements.Add(new OrganisationRequirement());
            });

这是 OrganisationRequirement

的 AuthorizationHandler
public class OrganisationHandler : AuthorizationHandler<OrganisationRequirement>
    {
        private readonly StatelessServiceContext _context;

        public OrganisationHandler(StatelessServiceContext context)
        {
            _context = context;
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OrganisationRequirement requirement)
        {
            if (CanRequest(context))
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }

            return Task.CompletedTask;
        }

        private bool CanRequest(AuthorizationHandlerContext context)
        {
            string OrgId = Encoding.Unicode.GetString(_context.InitializationData, 0, _context.InitializationData.Length);
            if (string.IsNullOrEmpty(OrgId))
            {
                return true;
            }

            if (context.User.HasClaim(c => c.Type == ClaimTypes.Role && (c.Value == RoleNames.SysAdmin)))
            {
                return true;
            }

            if (context.User.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == RoleNames.Service)
                && context.User.HasClaim(c => (c.Type == CustomClaimTypes.OrgCode) && (c.Value == "system")))
            {
                return true;
            }

            if (context.User.HasClaim(c => (c.Type == CustomClaimTypes.OrgCode) && c.Value == OrgId))
            {
                return true;
            }

            return false;
        }
    }

事实证明,如果您有一个 [HTTPGet] 方法对应于您的 post 方法并且不使用 [HTTPGet] 对其进行注释,则 post 请求将定向到该获取操作.

这会导致问题:

public class MyController : Controller
{

        [Authorize(Policy = "MyPolicy")]
        public async Task<IActionResult> MyAction(int id)
        {
            return View();
        }
        
        [HttpPost]
        [Authorize(Policy = "MyPolicy")]
        [Consumes("application/x-www-form-urlencoded")]
        public async Task<IActionResult> MyAction(MyModel model)
        {
            return View();
        }

}

这解决了问题:

public class MyController : Controller
{
        [HttpGet]
        [Authorize(Policy = "MyPolicy")]
        public async Task<IActionResult> MyAction(int id)
        {
            return View();
        }
        
        [HttpPost]
        [Authorize(Policy = "MyPolicy")]
        [Consumes("application/x-www-form-urlencoded")]            
        public async Task<IActionResult> MyAction(MyModel model)
        {
            return View();
        }

}