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

 


 


 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM