zoukankan      html  css  js  c++  java
  • asp.net core mvc 3.1 源码分析(四)

    AuthorizationApplicationModelProvider

    该类主要添加授权认证的过滤器

    先在Controller和Action中找到实现IAuthorizeData的特性,再根据IAuthorizeData创建AuthorizeFilter过滤器,把AuthorizeFilter添加到Controller和Action的Filters列表中

    具体的授权逻辑后面分开讲

    internal class AuthorizationApplicationModelProvider : IApplicationModelProvider
        {
            private readonly MvcOptions _mvcOptions;
            private readonly IAuthorizationPolicyProvider _policyProvider;
    
            public AuthorizationApplicationModelProvider(
                IAuthorizationPolicyProvider policyProvider,
                IOptions<MvcOptions> mvcOptions)
            {
                _policyProvider = policyProvider;
                _mvcOptions = mvcOptions.Value;
            }
    
            public int Order => -1000 + 10;
    
            public void OnProvidersExecuted(ApplicationModelProviderContext context)
            {
                // Intentionally empty.
            }
    
            public void OnProvidersExecuting(ApplicationModelProviderContext context)
            {
                if (context == null)
                {
                    throw new ArgumentNullException(nameof(context));
                }
    
                if (_mvcOptions.EnableEndpointRouting)
                {
                    // When using endpoint routing, the AuthorizationMiddleware does the work that Auth filters would otherwise perform.
                    // Consequently we do not need to convert authorization attributes to filters.
                    return;
                }
    
                foreach (var controllerModel in context.Result.Controllers)
                {
                    var controllerModelAuthData = controllerModel.Attributes.OfType<IAuthorizeData>().ToArray();
                    if (controllerModelAuthData.Length > 0)
                    {
                        controllerModel.Filters.Add(GetFilter(_policyProvider, controllerModelAuthData));
                    }
                    foreach (var attribute in controllerModel.Attributes.OfType<IAllowAnonymous>())
                    {
                        controllerModel.Filters.Add(new AllowAnonymousFilter());
                    }
    
                    foreach (var actionModel in controllerModel.Actions)
                    {
                        var actionModelAuthData = actionModel.Attributes.OfType<IAuthorizeData>().ToArray();
                        if (actionModelAuthData.Length > 0)
                        {
                            actionModel.Filters.Add(GetFilter(_policyProvider, actionModelAuthData));
                        }
    
                        foreach (var attribute in actionModel.Attributes.OfType<IAllowAnonymous>())
                        {
                            actionModel.Filters.Add(new AllowAnonymousFilter());
                        }
                    }
                }
            }
    
            public static AuthorizeFilter GetFilter(IAuthorizationPolicyProvider policyProvider, IEnumerable<IAuthorizeData> authData)
            {
                // The default policy provider will make the same policy for given input, so make it only once.
                // This will always execute synchronously.
                if (policyProvider.GetType() == typeof(DefaultAuthorizationPolicyProvider))
                {
                    var policy = AuthorizationPolicy.CombineAsync(policyProvider, authData).GetAwaiter().GetResult();
                    return new AuthorizeFilter(policy);
                }
                else
                {
                    return new AuthorizeFilter(policyProvider, authData);
                }
            }
        }

    ApiBehaviorApplicationModelProvider

    internal class ApiBehaviorApplicationModelProvider : IApplicationModelProvider
        {
            public ApiBehaviorApplicationModelProvider(
                IOptions<ApiBehaviorOptions> apiBehaviorOptions,
                IModelMetadataProvider modelMetadataProvider,
                IClientErrorFactory clientErrorFactory,
                ILoggerFactory loggerFactory)
            {
                var options = apiBehaviorOptions.Value;
    
                ActionModelConventions = new List<IActionModelConvention>()
                {
                    new ApiVisibilityConvention(),
                };
    
                if (!options.SuppressMapClientErrors)
                {
                    ActionModelConventions.Add(new ClientErrorResultFilterConvention());
                }
    
                if (!options.SuppressModelStateInvalidFilter)
                {
                    ActionModelConventions.Add(new InvalidModelStateFilterConvention());
                }
    
                if (!options.SuppressConsumesConstraintForFormFileParameters)
                {
                    ActionModelConventions.Add(new ConsumesConstraintForFormFileParameterConvention());
                }
    
                var defaultErrorType = options.SuppressMapClientErrors ? typeof(void) : typeof(ProblemDetails);
                var defaultErrorTypeAttribute = new ProducesErrorResponseTypeAttribute(defaultErrorType);
                ActionModelConventions.Add(new ApiConventionApplicationModelConvention(defaultErrorTypeAttribute));
    
                if (!options.SuppressInferBindingSourcesForParameters)
                {
                    ActionModelConventions.Add(new InferParameterBindingInfoConvention(modelMetadataProvider));
                }
            }
    
            /// <remarks>
            /// Order is set to execute after the <see cref="DefaultApplicationModelProvider"/> and allow any other user
            /// <see cref="IApplicationModelProvider"/> that configure routing to execute.
            /// </remarks>
            public int Order => -1000 + 100;
    
            public List<IActionModelConvention> ActionModelConventions { get; }
    
            public void OnProvidersExecuted(ApplicationModelProviderContext context)
            {
            }
    
            public void OnProvidersExecuting(ApplicationModelProviderContext context)
            {
                foreach (var controller in context.Result.Controllers)
                {
                    if (!IsApiController(controller))
                    {
                        continue;
                    }
    
                    foreach (var action in controller.Actions)
                    {
                        // Ensure ApiController is set up correctly
                        EnsureActionIsAttributeRouted(action);
    
                        foreach (var convention in ActionModelConventions)
                        {
                            convention.Apply(action);
                        }
                    }
                }
            }
    
            private static void EnsureActionIsAttributeRouted(ActionModel actionModel)
            {
                if (!IsAttributeRouted(actionModel.Controller.Selectors) &&
                    !IsAttributeRouted(actionModel.Selectors))
                {
                    // Require attribute routing with controllers annotated with ApiControllerAttribute
                    var message = Resources.FormatApiController_AttributeRouteRequired(
                         actionModel.DisplayName,
                        nameof(ApiControllerAttribute));
                    throw new InvalidOperationException(message);
                }
    
                bool IsAttributeRouted(IList<SelectorModel> selectorModel)
                {
                    for (var i = 0; i < selectorModel.Count; i++)
                    {
                        if (selectorModel[i].AttributeRouteModel != null)
                        {
                            return true;
                        }
                    }
    
                    return false;
                }
            }
    
            private static bool IsApiController(ControllerModel controller)
            {
                if (controller.Attributes.OfType<IApiBehaviorMetadata>().Any())
                {
                    return true;
                }
    
                var controllerAssembly = controller.ControllerType.Assembly;
                var assemblyAttributes = controllerAssembly.GetCustomAttributes();
                return assemblyAttributes.OfType<IApiBehaviorMetadata>().Any();
            }
        }

    该类涉及到webapi方面

     对ActionModel设置相关的属性和过滤器

  • 相关阅读:
    java8新特性学习五(接口中的默认方法与静态方法)
    java8新特性学习四(Optional类)
    [record]WebLogic域之创建-文本界面
    [转]java 关于httpclient 请求https (如何绕过证书验证)
    数组与串,串的实现,KMP,BF算法
    git
    nginx设置重写规则
    深入PHP 第三章笔记
    进程和线程
    JS 获取 iframe内元素,及iframe与html调用
  • 原文地址:https://www.cnblogs.com/lanpingwang/p/12642751.html
Copyright © 2011-2022 走看看