zoukankan      html  css  js  c++  java
  • ABP框架源码学习之授权逻辑

    asp.net core的默认的几种授权方法参考“雨夜朦胧”的系列博客,这里要强调的是asp.net core mvc中的授权和asp.net mvc中的授权不一样,建议先看前面“雨夜朦胧”的博客。

    Abp中Controller里面用到的权限验证类为:AbpMvcAuthorizeAttribute,ApplicationService里面用到的权限验证类为:AbpAuthorizeAttribute(见下图)。

    AbpMvcAuthorizeAttributeAbpAuthorizeAttribute这两个类全部继承自IAbpAuthorizeAttribute(重要!!!),下面是这两个类的源码。

     1 namespace Abp.Authorization
     2 {
     3     /// <summary>
     4     /// This attribute is used on a method of an Application Service (A class that implements <see cref="IApplicationService"/>)
     5     /// to make that method usable only by authorized users.
     6     /// </summary>
     7     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
     8     public class AbpAuthorizeAttribute : Attribute, IAbpAuthorizeAttribute
     9     {
    10         /// <summary>
    11         /// A list of permissions to authorize.
    12         /// </summary>
    13         public string[] Permissions { get; }
    14 
    15         /// <summary>
    16         /// If this property is set to true, all of the <see cref="Permissions"/> must be granted.
    17         /// If it's false, at least one of the <see cref="Permissions"/> must be granted.
    18         /// Default: false.
    19         /// </summary>
    20         public bool RequireAllPermissions { get; set; }
    21 
    22         /// <summary>
    23         /// Creates a new instance of <see cref="AbpAuthorizeAttribute"/> class.
    24         /// </summary>
    25         /// <param name="permissions">A list of permissions to authorize</param>
    26         public AbpAuthorizeAttribute(params string[] permissions)
    27         {
    28             Permissions = permissions;
    29         }
    30     }
    31 }
    View Code
     1 namespace Abp.AspNetCore.Mvc.Authorization
     2 {
     3     /// <summary>
     4     /// This attribute is used on an action of an MVC <see cref="Controller"/>
     5     /// to make that action usable only by authorized users. 
     6     /// </summary>
     7     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
     8     public class AbpMvcAuthorizeAttribute : AuthorizeAttribute, IAbpAuthorizeAttribute
     9     {
    10         /// <inheritdoc/>
    11         public string[] Permissions { get; set; }
    12 
    13         /// <inheritdoc/>
    14         public bool RequireAllPermissions { get; set; }
    15 
    16         /// <summary>
    17         /// Creates a new instance of <see cref="AbpMvcAuthorizeAttribute"/> class.
    18         /// </summary>
    19         /// <param name="permissions">A list of permissions to authorize</param>
    20         public AbpMvcAuthorizeAttribute(params string[] permissions)
    21         {
    22             Permissions = permissions;
    23         }
    24     }
    25 }
    View Code

    重点来啦!!!

     1 namespace Abp.AspNetCore.Mvc.Authorization
     2 {
     3     public class AbpAuthorizationFilter : IAsyncAuthorizationFilter, ITransientDependency
     4     {
     5         public ILogger Logger { get; set; }
     6 
     7         private readonly IAuthorizationHelper _authorizationHelper;
     8         private readonly IErrorInfoBuilder _errorInfoBuilder;
     9         private readonly IEventBus _eventBus;
    10 
    11         public AbpAuthorizationFilter(
    12             IAuthorizationHelper authorizationHelper,
    13             IErrorInfoBuilder errorInfoBuilder,
    14             IEventBus eventBus)
    15         {
    16             _authorizationHelper = authorizationHelper;
    17             _errorInfoBuilder = errorInfoBuilder;
    18             _eventBus = eventBus;
    19             Logger = NullLogger.Instance;
    20         }
    21 
    22         public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    23         {
    24             // 判断context中是否有继承IAllowAnoymousFilter,有则跳出方法即验证成功
    25             if (context.Filters.Any(item => item is IAllowAnonymousFilter))
    26             {
    27                 return;
    28             }
    29        //判断是否是Controller,具体方法见下面第一张截图
    30             if (!context.ActionDescriptor.IsControllerAction())
    31             {
    32                 return;
    33             }
    34 
    35             //TODO: Avoid using try/catch, use conditional checking
    36             try
    37             {
    38                 await _authorizationHelper.AuthorizeAsync(
    39                     context.ActionDescriptor.GetMethodInfo(),
    40                     context.ActionDescriptor.GetMethodInfo().DeclaringType
    41                 );
    42             }
    43             catch (AbpAuthorizationException ex)
    44             {
    45                 Logger.Warn(ex.ToString(), ex);
    46 
    47                 _eventBus.Trigger(this, new AbpHandledExceptionData(ex));
    48 
    49                 if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType))
    50                 {
    51                     context.Result = new ObjectResult(new AjaxResponse(_errorInfoBuilder.BuildForException(ex), true))
    52                     {
    53                         StatusCode = context.HttpContext.User.Identity.IsAuthenticated
    54                             ? (int) System.Net.HttpStatusCode.Forbidden
    55                             : (int) System.Net.HttpStatusCode.Unauthorized
    56                     };
    57                 }
    58                 else
    59                 {
    60                     context.Result = new ChallengeResult();
    61                 }
    62             }
    63             catch (Exception ex)
    64             {
    65                 Logger.Error(ex.ToString(), ex);
    66 
    67                 _eventBus.Trigger(this, new AbpHandledExceptionData(ex));
    68 
    69                 if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType))
    70                 {
    71                     context.Result = new ObjectResult(new AjaxResponse(_errorInfoBuilder.BuildForException(ex)))
    72                     {
    73                         StatusCode = (int) System.Net.HttpStatusCode.InternalServerError
    74                     };
    75                 }
    76                 else
    77                 {
    78                     //TODO: How to return Error page?
    79                     context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.InternalServerError);
    80                 }
    81             }
    82         }
    83     }
    84 }
     
    AbpAuthorizationFilter继承自IAsyncAuthorizationFilter和ITransientDependency,其中继承自ITransientDependency 是为了注入这个类,继承IAsyncAuthorizationFilter这个接口下面会写到。
    其中AbpAuthorizationFilter类的OnAuthorizationAsync这个方法是验证授权的最重要的一个地方,其中_authorizationHelper.AuthorizeAsync是通过反射得到是否有继承自IAbpAuthorizeAttribute接口的特性,即AbpMvcAuthorizeAttributeAbpAuthorizeAttribute,然后得到这个特性标识的权限,然后PermissionChecker检验用户是否具有这个权限。
     
    现在我们知道AbpAuthorizationFilter的主要任务就是通过判断controller或者service的标识的权限对比用户是否具有这个权限来达到授权验证。那AbpAuthorizationFilter怎么触发的呢,也就是什么时候调用的呢,,从下图我们可以看出当我们调用AddAbp这个方法时,也就是在Startup类里面调用AddAbp时,就会在MvcOptions里面FilterCollection里面添加AbpAuthorizationFilter,当我们访问一个Controller或者ApplicationService时就会触发这个filter,判断权限。

    拓展:当我们有某个业务需要用到AOP时,但又不想使用一些第三方框架,我们就可以借鉴上面的方法,定义一个特性,然后定义一个Filter,在Filter里面判断Controller等是否使用这些特性,并且特性的属性是否符合我们的需求,最后在Startup里面AddMvc时将这个Filter添加到FilterCollection里面。例如下图,自动验证AntiforgeryToken



  • 相关阅读:
    Go标准库Context
    事务并发处理: DB+ORM+逻辑代码
    日志:slf4j+log4j+maven配置
    Shiro workshop
    JSP Workshop
    sql records
    Java内存模型(JMM)
    Application, JDBC, 数据库连接池, Session, 数据库的关系
    Java位操作全面总结
    Effective Java总结
  • 原文地址:https://www.cnblogs.com/gebi-laowang/p/8474357.html
Copyright © 2011-2022 走看看