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