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

原文地址:https://www.cnblogs.com/lanpingwang/p/12642751.html

时间: 2024-10-12 17:17:40

asp.net core mvc 3.1 源码分析(四)的相关文章

asp.net core mvc 3.1 源码分析(一)

我们先看下IApplicationBuilder接口的扩展方法UseMvc public static IApplicationBuilder UseMvc( this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (configureRoutes == null) {

asp.net core mvc 3.1 源码分析(五)

创建完ApplicationModel后,调用ControllerActionDescriptorBuilder类的Build方法创建对应的ControllerActionDescriptor internal static class ControllerActionDescriptorBuilder { public static IList<ControllerActionDescriptor> Build(ApplicationModel application) { return A

各类最新Asp .Net Core 项目和示例源码

1.网站地址:http://www.freeboygirl.com2.网站Asp .Net Core 资料http://www.freeboygirl.com/blog/tag/asp%20net%20core3.各类最新Asp .Net Core 项目和示例源码? github.com/freeboygirl 4.微信公众号:AspNetCore 5.直接在微信公众号发消息即可.

Nouveau源码分析(四):NVIDIA设备初始化之nouveau_drm_load (1)

Nouveau源码分析(四) probe函数成功返回之后,DRM模块就会调用struct drm_driver的load函数,对应nouveau的nouveau_drm_load. 这个函数虽然看起来不是特别长,但每一个调用的函数展开后就会变得非常长了! // /drivers/gpu/drm/nouveau/nouveau_drm.c 364 static int 365 nouveau_drm_load(struct drm_device *dev, unsigned long flags)

baksmali和smali源码分析(四)

baksmali 首先执行的第一个main 函数     public static void main(String[] args) throws IOException {         Locale locale = new Locale("en", "US");         Locale.setDefault(locale);         CommandLineParser parser = new PosixParser();         C

mybatis源码分析(四) mybatis与spring事务管理分析

mybatis源码分析(四) mybatis与spring事务管理分析 一丶从jdbc的角度理解什么是事务 从mysql获取一个连接之后, 默认是自动提交, 即执行完sql之后, 就会提交事务. 这种事务的范围是一条sql语句. 将该连接设置非自动提交, 可以执行多条sql语句, 然后由程序决定是提交事务, 还是回滚事务. 这也是我们常说的事务. Connection connection = dataSource.getConnection(); // connection.setTransa

Spring MVC初始化部分源码分析

首先定位到org.springframework.context.support.AbstractApplicationContext中的refresh()方法: public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh

ABP源码分析四十一:ZERO的Audit,Setting,Background Job

AuditLog: 继承自Entity<long>的实体类.封装AuditLog的信息. AuditingStore: 实现了IAuditingStore接口,实现了将AuditLog的信息保存到数据库的功能.其通过IRepository<AuditLog, long>实例完成对数据库的操作. BackgroundJobStore :  实现了IBackgroundJobStore接口,通过IRepository<BackgroundJobInfo, long>完成对B

ABP源码分析四十六:ABP ZERO中的Ldap模块

通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供DefautValue.主要提供配置访问AD数据库的账号信息. LdapSettings/ILdapSettings:通过settingManager获取LDAP settings AbpZeroLdapModuleConfig/IAbpZeroLdapModuleConfig: 提供激活Ldap认证的配置.