为什么在添加全局授权筛选器时调用两次授权处理程序? [英] why Authorization Handler invoked two time when added a global authorization filter?

查看:0
本文介绍了为什么在添加全局授权筛选器时调用两次授权处理程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在ASP.NET核心MVC 3.1中使用了基于策略的授权,我对Read有一个名为ReadAuthorizationRequirements的授权要求,我还有一个全局IPAllowweAuthorizationRequirements,它检查用户的IP并检查是否允许此IP继承上下文。

问题是,当我在第一次Invoke中添加两次调用的全局授权筛选器读取需求时,其资源为Microsoft.AspNetCore.Routing.RouteEndpoint在第二次Invoke中其资源为Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.AuthorizationFilterContextSealed 这会阻止上下文成功授权。

我的Startup.cs如下:

           services.AddAuthorization(options =>
            {
                options.FallbackPolicy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
            });

            services.AddControllersWithViews(options =>
            {                
                options.Filters.Add(new AuthorizeFilter(policy: Constants.Authorization.IpAllowed));
                options.Filters.Add(typeof(Filters.RequestLoggingAttribute));
            });

ReadAuthorizationHandler.cs

 public class ReadAuthorizationHandler : AuthorizationHandler<ReadAuthorizationRequirement>
    {
        private readonly IApplicationRouteService _applicationRouteService;

        public ReadAuthorizationHandler(IApplicationRouteService applicationRouteService)
        {
            _applicationRouteService = applicationRouteService;
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ReadAuthorizationRequirement requirement)
        {
            var roles = AuthorizationHanderHelper.FindRole(_applicationRouteService, context, requirement);

            if (roles.Any(role => role.Read == true))
            {
                context.Succeed(requirement);
            }

            return Task.CompletedTask;
        }
    }

IpAllen weAuthorizationHandler.cs

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IpAllowedAuthorizationRequirement requirement)
        {
            if (context.Resource is Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext mvcContext)
            {
                var userIps = ((ClaimsIdentity)context.User.Identity).Claims
                    .Where(c => c.Type == Constants.Authorization.ClaimTypes.IpAddress)
                    .Select(c => c.Value).ToList();

                var currentIp = mvcContext.HttpContext.Connection.RemoteIpAddress;
                
                var bytes = currentIp.GetAddressBytes();
                var badIp = true;
                foreach (var address in userIps)
                {                    
                    if (IPAddress.TryParse(address, out IPAddress testIp))
                    {
                        if (testIp.GetAddressBytes().SequenceEqual(bytes))
                        {
                            badIp = false;
                            break;
                        }
                    }
                }

                if (!badIp)
                {
                    context.Succeed(requirement);
                }
                else
                {
                    var routeData = mvcContext.RouteData;
                    var action = routeData.Values["action"] as string;
                    var controller = routeData.Values["controller"] as string;
                    var area = routeData.DataTokens["area"] as string;

                    if (string.IsNullOrEmpty(area) && controller == "Account" && action == "AccessDenied")
                    {
                        mvcContext.ModelState.TryAddModelError("", $"IP izni verilmemiştir! (IP: {currentIp})");
                        context.Succeed(requirement);
                    }
                    else
                    {
                        context.Fail();
                    }
                }
            }

            return Task.CompletedTask;
        }
这是要在IpAllowed处理程序上读取的调用的图片: 1-第一个调用发生在读授权处理程序中,并且上下文为端点(此调用成功):

在读授权处理程序中发生了2秒的调用,上下文是MVC的AuthorizationFilterContext,这次失败。在第二个调用中,IpAllowed处于挂起的要求中。

推荐答案

这里提到 Setting Global Authorization policies using defaultpolicy and the fallback policy in aspnet core 3

here

我对ASP.NET MVC核心使用了旧式全局授权筛选器,这在ASP.NET核心2.2中是可以的,但在3.0+中使用终结点路由时它不能像预期的那样工作。

所以我更改了代码,如下所示: Start.cs:

从配置服务中删除了回退策略,因为我添加了IpAllowed策略作为全局要求,如下所示。 从配置服务方法的选项中删除了全局授权筛选器,并在app.useEndpoint的配置方法中添加了需要授权,如下所示:

 app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute().RequireAuthorization(Constants.Authorization.IpAllowed);
});

IpAllen weAuthorizationHandler.cs

更新处理程序如下:

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IpAllowedAuthorizationRequirement requirement)
        {
            if (context.Resource is Microsoft.AspNetCore.Routing.RouteEndpoint endpoint)
            {
                var userIps = ((ClaimsIdentity)context.User.Identity).Claims
                    .Where(c => c.Type == Constants.Authorization.ClaimTypes.IpAddress)
                    .Select(c => c.Value).ToList();
                
                var currentIp = _contextAccessor?.HttpContext.Connection.RemoteIpAddress;
                
                if(currentIp == null)
                {
                    context.Fail();
                    return Task.CompletedTask;
                }

                var bytes = currentIp.GetAddressBytes();
                var badIp = true;
                foreach (var address in userIps)
                {                    
                    if (IPAddress.TryParse(address, out IPAddress testIp))
                    {
                        if (testIp.GetAddressBytes().SequenceEqual(bytes))
                        {
                            badIp = false;
                            break;
                        }
                    }
                }

                if (!badIp)
                {
                    context.Succeed(requirement);
                }
                else
                {
                    context.Fail();
                }
            }

            return Task.CompletedTask;
        }

这篇关于为什么在添加全局授权筛选器时调用两次授权处理程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆