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设置相关的属性和过滤器

  • 相关阅读:
    Linux下Subversion的使用
    python3之HTML、CSS学习
    Python成长之路 常用模块与正则表达式
    Css3 列表布局 两列或者多列布局整理
    .net 通过代码控制GridView显示列
    .net 创建一个页面级全局datatable的方法
    .net 将分页展示的GridView的全部数据 导出excel
    .net 如何判断dataset是否为空
    sql 全表结构备份
    sql 把一个表中的某一列赋值到另一个表中的某一列
  • 原文地址:https://www.cnblogs.com/lanpingwang/p/12642751.html
Copyright © 2011-2022 走看看