예제 #1
0
        /// <summary>
        /// This method will go an execute the authorization filters for the controller action, if any fail
        /// it will return their response, otherwise we'll return null.
        /// </summary>
        /// <param name="controllerContext"></param>
        internal static async Task <HttpResponseMessage> InvokeAuthorizationFiltersForRequest(this HttpControllerContext controllerContext)
        {
            var controllerDescriptor = controllerContext.ControllerDescriptor;
            var controllerServices   = controllerDescriptor.Configuration.Services;
            var actionDescriptor     = controllerServices.GetActionSelector().SelectAction(controllerContext);
            var actionContext        = new HttpActionContext(controllerContext, actionDescriptor);
            var filters        = actionDescriptor.GetFilterPipeline();
            var filterGrouping = new FilterGrouping(filters);
            var actionFilters  = filterGrouping.ActionFilters;
            // Because the continuation gets built from the inside out we need to reverse the filter list
            // so that least specific filters (Global) get run first and the most specific filters (Action) get run last.
            var authorizationFilters = filterGrouping.AuthorizationFilters.Reverse().ToArray();

            if (authorizationFilters.Any())
            {
                var cancelToken  = new CancellationToken();
                var filterResult = await FilterContinuation(actionContext, cancelToken, authorizationFilters, 0);

                if (filterResult != null)
                {
                    //this means that the authorization filter has returned a result - unauthorized so we cannot continue
                    return(filterResult);
                }
            }
            return(null);
        }
        /// <summary>
        /// This method will go an execute the authorization filters for the controller action, if any fail
        /// it will return their response, otherwise we'll return null.
        /// </summary>
        /// <param name="controllerContext"></param>
        internal static async Task<HttpResponseMessage> InvokeAuthorizationFiltersForRequest(this HttpControllerContext controllerContext)
        {
            var controllerDescriptor = controllerContext.ControllerDescriptor;
            var controllerServices = controllerDescriptor.Configuration.Services;
            var actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext);
            var actionContext = new HttpActionContext(controllerContext, actionDescriptor);
            var filters = actionDescriptor.GetFilterPipeline();
            var filterGrouping = new FilterGrouping(filters);
            var actionFilters = filterGrouping.ActionFilters;
            // Because the continuation gets built from the inside out we need to reverse the filter list
            // so that least specific filters (Global) get run first and the most specific filters (Action) get run last.
            var authorizationFilters = filterGrouping.AuthorizationFilters.Reverse().ToArray();

            if (authorizationFilters.Any())
            {
                var cancelToken = new CancellationToken();           
                var filterResult = await FilterContinuation(actionContext, cancelToken, authorizationFilters, 0);
                if (filterResult != null)
                {
                    //this means that the authorization filter has returned a result - unauthorized so we cannot continue
                    return filterResult;
                }                    
            }
            return null;
        }
예제 #3
0
        public virtual Task <HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
        {
            if (_initialized)
            {
                // if user has registered a controller factory which produces the same controller instance, we should throw here
                throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name);
            }

            Initialize(controllerContext);

            // We can't be reused, and we know we're disposable, so make sure we go away when
            // the request has been completed.
            if (Request != null)
            {
                Request.RegisterForDispose(this);
            }

            HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor;
            ServicesContainer        controllerServices   = controllerDescriptor.Configuration.Services;

            HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext);

            ActionContext.ActionDescriptor = actionDescriptor;
            if (Request != null)
            {
                Request.SetActionDescriptor(actionDescriptor);
            }

            FilterGrouping filterGrouping = actionDescriptor.GetFilterGrouping();

            IActionFilter[]         actionFilters         = filterGrouping.ActionFilters;
            IAuthenticationFilter[] authenticationFilters = filterGrouping.AuthenticationFilters;
            IAuthorizationFilter[]  authorizationFilters  = filterGrouping.AuthorizationFilters;
            IExceptionFilter[]      exceptionFilters      = filterGrouping.ExceptionFilters;

            IHttpActionResult result = new ActionFilterResult(actionDescriptor.ActionBinding, ActionContext,
                                                              controllerServices, actionFilters);

            if (authorizationFilters.Length > 0)
            {
                result = new AuthorizationFilterResult(ActionContext, authorizationFilters, result);
            }
            if (authenticationFilters.Length > 0)
            {
                result = new AuthenticationFilterResult(ActionContext, this, authenticationFilters, result);
            }
            if (exceptionFilters.Length > 0)
            {
                IExceptionLogger  exceptionLogger  = ExceptionServices.GetLogger(controllerServices);
                IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices);
                result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler,
                                                   result);
            }

            return(result.ExecuteAsync(cancellationToken));
        }
예제 #4
0
    /// <summary>
    ///     Invokes the authorization filters for the controller action.
    /// </summary>
    /// <returns>Whether the user is authenticated or not.</returns>
    internal static async Task <bool> InvokeAuthorizationFiltersForRequest(this ControllerContext controllerContext, ActionContext actionContext)
    {
        ControllerActionDescriptor actionDescriptor = controllerContext.ActionDescriptor;

        var metadataCollection =
            new EndpointMetadataCollection(actionDescriptor.EndpointMetadata.Union(new[] { actionDescriptor }));

        IReadOnlyList <IAuthorizeData> authorizeData  = metadataCollection.GetOrderedMetadata <IAuthorizeData>();
        IAuthorizationPolicyProvider   policyProvider = controllerContext.HttpContext.RequestServices
                                                        .GetRequiredService <IAuthorizationPolicyProvider>();
        AuthorizationPolicy?policy = await AuthorizationPolicy.CombineAsync(policyProvider, authorizeData);

        if (policy is not null)
        {
            IPolicyEvaluator policyEvaluator =
                controllerContext.HttpContext.RequestServices.GetRequiredService <IPolicyEvaluator>();
            AuthenticateResult authenticateResult =
                await policyEvaluator.AuthenticateAsync(policy, controllerContext.HttpContext);

            if (!authenticateResult.Succeeded)
            {
                return(false);
            }

            // TODO this is super hacky, but we rely on the FeatureAuthorizeHandler can still handle endpoints
            // (The way before .NET 5). The .NET 5 way would need to use han http context, for the "inner" request
            // with the nested controller
            var resource = new Endpoint(null, metadataCollection, null);
            PolicyAuthorizationResult authorizeResult =
                await policyEvaluator.AuthorizeAsync(policy, authenticateResult, controllerContext.HttpContext, resource);

            if (!authorizeResult.Succeeded)
            {
                return(false);
            }
        }

        IList <FilterDescriptor> filters = actionDescriptor.FilterDescriptors;
        var filterGrouping = new FilterGrouping(filters, controllerContext.HttpContext.RequestServices);

        // because the continuation gets built from the inside out we need to reverse the filter list
        // so that least specific filters (Global) get run first and the most specific filters (Action) get run last.
        var authorizationFilters      = filterGrouping.AuthorizationFilters.Reverse().ToList();
        var asyncAuthorizationFilters = filterGrouping.AsyncAuthorizationFilters.Reverse().ToList();

        if (authorizationFilters.Count == 0 && asyncAuthorizationFilters.Count == 0)
        {
            return(true);
        }

        // if the authorization filter returns a result, it means it failed to authorize
        var authorizationFilterContext =
            new AuthorizationFilterContext(actionContext, filters.Select(x => x.Filter).ToArray());

        return(await ExecuteAuthorizationFiltersAsync(authorizationFilterContext, authorizationFilters, asyncAuthorizationFilters));
    }
예제 #5
0
        public void GetDeliveries_LightWeightsSelector_ultipleParcelsTwoRecipients_ReturnsSizeTwoList()
        {
            // Arrange
            var selector = new FilterGrouping(MultipleParcelsTwoRecipients);
            // Act
            var selectedItems = selector.GetDeliveries().ToList();

            // Assert
            Assert.AreEqual(selectedItems.Count(), 2);
        }
예제 #6
0
        public void GetDeliveries_FilterGrouping_MultipleParcelsOneRecipients_ReturnsSizeOneList()
        {
            // Arrange
            var selector = new FilterGrouping(MultipleParcelsOneRecipients);
            // Act
            var selectedItems = selector.GetDeliveries().ToList();

            // Assert
            Assert.AreEqual(selectedItems.Count(), 1);
            Assert.AreEqual(selectedItems[0].weight, 105);
            Assert.AreEqual(selectedItems[0].value, 1501);
        }
예제 #7
0
        public virtual Task <HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
        {
            if (_request != null)
            {
                // if user has registered a controller factory which produces the same controller instance, we should throw here
                throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name);
            }

            Initialize(controllerContext);

            // We can't be reused, and we know we're disposable, so make sure we go away when
            // the request has been completed.
            if (_request != null)
            {
                _request.RegisterForDispose(this);
            }

            HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor;
            ServicesContainer        controllerServices   = controllerDescriptor.Configuration.Services;
            HttpActionDescriptor     actionDescriptor     = controllerServices.GetActionSelector().SelectAction(controllerContext);
            HttpActionContext        actionContext        = new HttpActionContext(controllerContext, actionDescriptor);

            IEnumerable <FilterInfo> filters = actionDescriptor.GetFilterPipeline();

            FilterGrouping filterGrouping = new FilterGrouping(filters);

            IEnumerable <IActionFilter>        actionFilters        = filterGrouping.ActionFilters;
            IEnumerable <IAuthorizationFilter> authorizationFilters = filterGrouping.AuthorizationFilters;
            IEnumerable <IExceptionFilter>     exceptionFilters     = filterGrouping.ExceptionFilters;

            // Func<Task<HttpResponseMessage>>
            Task <HttpResponseMessage> result = InvokeActionWithAuthorizationFilters(actionContext, cancellationToken, authorizationFilters, () =>
            {
                HttpActionBinding actionBinding = actionDescriptor.ActionBinding;
                Task bindTask = actionBinding.ExecuteBindingAsync(actionContext, cancellationToken);
                return(bindTask.Then <HttpResponseMessage>(() =>
                {
                    _modelState = actionContext.ModelState;
                    Func <Task <HttpResponseMessage> > invokeFunc = InvokeActionWithActionFilters(actionContext, cancellationToken, actionFilters, () =>
                    {
                        return controllerServices.GetActionInvoker().InvokeActionAsync(actionContext, cancellationToken);
                    });
                    return invokeFunc();
                }));
            })();

            result = InvokeActionWithExceptionFilters(result, actionContext, cancellationToken, exceptionFilters);

            return(result);
        }
예제 #8
0
        /// <summary>
        /// Invokes the authorization filters for the controller action.
        /// </summary>
        /// <returns>The response of the first filter returning a result, if any, otherwise null (authorized).</returns>
        internal static async Task <HttpResponseMessage> InvokeAuthorizationFiltersForRequest(this HttpControllerContext controllerContext)
        {
            var controllerDescriptor = controllerContext.ControllerDescriptor;
            var controllerServices   = controllerDescriptor.Configuration.Services;
            var actionDescriptor     = controllerServices.GetActionSelector().SelectAction(controllerContext);

            var filters        = actionDescriptor.GetFilterPipeline();
            var filterGrouping = new FilterGrouping(filters);

            // because the continuation gets built from the inside out we need to reverse the filter list
            // so that least specific filters (Global) get run first and the most specific filters (Action) get run last.
            var authorizationFilters = filterGrouping.AuthorizationFilters.Reverse().ToList();

            if (authorizationFilters.Count == 0)
            {
                return(null);
            }

            // if the authorization filter returns a result, it means it failed to authorize
            var actionContext = new HttpActionContext(controllerContext, actionDescriptor);

            return(await ExecuteAuthorizationFiltersAsync(actionContext, CancellationToken.None, authorizationFilters));
        }