asp.net core的默認的幾種授權方法參考“雨夜朦朧”的系列博客,這里要強調的是asp.net core mvc中的授權和asp.net mvc中的授權不一樣,建議先看前面“雨夜朦朧”的博客。
Abp中Controller里面用到的權限驗證類為:AbpMvcAuthorizeAttribute,ApplicationService里面用到的權限驗證類為:AbpAuthorizeAttribute(見下圖)。
AbpMvcAuthorizeAttribute和AbpAuthorizeAttribute這兩個類全部繼承自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 }

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 }
重點來啦!!!
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
接口的特性,即AbpMvcAuthorizeAttribute和AbpAuthorizeAttribute,然后得到這個特性標識的權限,然后PermissionChecker檢驗用戶是否具有這個權限。
現在我們知道AbpAuthorizationFilter的主要任務就是通過判斷controller或者service的標識的權限對比用戶是否具有這個權限來達到授權驗證。那AbpAuthorizationFilter怎么觸發的呢,也就是什么時候調用的呢,,從下圖我們可以看出當我們調用AddAbp這個方法時,也就是在Startup類里面調用AddAbp時,就會在MvcOptions里面FilterCollection里面添加AbpAuthorizationFilter,當我們訪問一個Controller或者ApplicationService時就會觸發這個filter,判斷權限。


拓展:當我們有某個業務需要用到AOP時,但又不想使用一些第三方框架,我們就可以借鑒上面的方法,定義一個特性,然后定義一個Filter,在Filter里面判斷Controller等是否使用這些特性,並且特性的屬性是否符合我們的需求,最后在Startup里面AddMvc時將這個Filter添加到FilterCollection里面。例如下圖,自動驗證AntiforgeryToken