ASP.NET Core 认证与授权[6]:授权策略是怎么执行的?

本文深入探讨了ASP.NET Core授权策略的执行过程,从MVC中的授权开始,涉及AuthorizationApplicationModelProvider、AuthorizeFilter、IPolicyEvaluator等关键组件。通过IPolicyEvaluator的AuthenticateAsync和AuthorizeAsync方法,解释了如何处理AuthenticationSchemes和Requirements。文章还介绍了IAuthorizationService、IAuthorizationPolicyProvider、IAuthorizationHandlerContextFactory、IAuthorizationHandlerProvider和IAuthorizationEvaluator的角色,揭示了授权决策的制定过程。
摘要由CSDN通过智能技术生成

在上一章中ASP.NET Core 认证与授权[5]:初识授权,详细介绍了 ASP.NET Core 中的授权策略,在需要授权时,只需要在对应的Controler或者Action上面打上[Authorize]特性,并指定要执行的策略名称即可,但是,授权策略是怎么执行的呢?怀着一颗好奇的心,忍不住来探索一下它的执行流程。

在《(上一章》中提到,AuthorizeAttribute只是一个简单的实现了IAuthorizeData接口的特性,并且在 ASP.NET Core 授权系统中并没有使用到它。我们知道在认证中,还有一个UseAuthentication扩展方法来激活认证系统,但是在授权中并没有类似的机制。

这是因为当我们使用[Authorize]通常是在MVC中,由MVC来负责激活授权系统。本来在这个系列的文章中,我并不想涉及到MVC的知识,但是为了能更好的理解授权系统的执行,就来简单介绍一下MVC中与授权相关的知识。

MVC中的授权

当我们使用MVC时,首先会调用MVC的AddMvc扩展方法,用来注册一些MVC相关的服务:

public static IMvcBuilder AddMvc(this IServiceCollection services){    var builder = services.AddMvcCore();

    builder.AddAuthorization();

    ...
}public static IMvcCoreBuilder AddAuthorization(this IMvcCoreBuilder builder){
    AddAuthorizationServices(builder.Services);    return builder;
}internal static void AddAuthorizationServices(IServiceCollection services){
    services.AddAuthenticationCore();
    services.AddAuthorization();
    services.AddAuthorizationPolicyEvaluator();

    services.TryAddEnumerable(
        ServiceDescriptor.Transient<IApplicationModelProvider, AuthorizationApplicationModelProvider>());
}

在上面AddAuthorizationServices中的前三个方法都属于 ASP.NET Core 《Security》项目中提供的扩展方法,其中前两个在前面几章已经介绍过了,对于AddAuthorizationPolicyEvaluator放到后面再来介绍,我们先来看一下MVC中的AuthorizationApplicationModelProvider

AuthorizationApplicationModelProvider

在MVC中有一个ApplicationModel的概念,它用来封装ControllerFilterApiExplorer等。对应的,在MVC中还提供了一系列的ApplicationModelProvider来初始化ApplicationModel的各个部分,而AuthorizationApplicationModelProvider就是用来初始化与授权相关的部分。

public class AuthorizationApplicationModelProvider : IApplicationModelProvider{   
 public void OnProvidersExecuting(ApplicationModelProviderContext context)    {        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());                }            }        }    } }

如上,首先查找每个Controller中实现了IAuthorizeData接口的特性,然后将其转化为AuthorizeFilter并添加到Controller的Filter集合中,紧接着再查找实现了IAllowAnonymous接口的特性,将其转化为AllowAnonymousFilter过滤器也添加到Filter集合中,然后以同样的逻辑查找Action上的特性并添加到Action的Filter集合中。

其中的关键点就是将IAuthorizeData(也就是通过我们熟悉的[Authorize]特性)转化为MVC中的AuthorizeFilter过滤器:

public static AuthorizeFilter GetFilter(IAuthorizationPolicyProvider policyProvider, IEnumerable<IAuthorizeData> authData){    if (policyProvider.GetType() == typeof(DefaultAuthorizationPolicyProvider))
    {        var policy = AuthorizationPolicy.CombineAsync(policyProvider, authData).GetAwaiter().GetResult();        return new AuthorizeFilter(policy);
    }    else
    {        return new AuthorizeFilter(policyProvider, authData);
    }
}

CombineAsync在上一章的《AuthorizationPolicy》中已经介绍过了,我们往下看看AuthorizeFilter的实现。

AuthorizeFilter

在MVC中有一个AuthorizeFilter过滤器,类似我们在ASP.NET 4.x中所熟悉的[Authorize],它实现了IAsyncAuthorizationFilter接口,定义如下:

public class AuthorizeFilter : IAsyncAuthorizationFilter, IFilterFactory{   
 public AuthorizeFilter(AuthorizationPolicy policy) {}  
   public AuthorizeFilter(IAuthorizationPolicyProvider policyProvider, IEnumerable<IAuthorizeData> authorizeData) : this(authorizeData) {}    public AuthorizeFilter(IEnumerable<IAuthorizeData> authorizeData) {}    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值