asp.net core的默认的几种授权方法参考“雨夜朦胧”的系列博客,这里要强调的是asp.net core mvc中的授权和asp.net mvc中的授权不一样,建议先看前面“雨夜朦胧”的博客。
Abp中Controller里面用到的权限验证类为:AbpMvcAuthorizeAttribute,ApplicationService里面用到的权限验证类为:AbpAuthorizeAttribute(见下图)。
AbpMvcAuthorizeAttribute和AbpAuthorizeAttribute这两个类全部继承自IAbpAuthorizeAttribute(重要!!!),下面是这两个类的源码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
![](https://images2018.cnblogs.com/blog/707701/201802/707701-20180227092150411-7637966.png)
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,判断权限。
![](https://images2018.cnblogs.com/blog/707701/201802/707701-20180227093654373-469113917.png)
![](https://images2018.cnblogs.com/blog/707701/201802/707701-20180227094258879-180266020.png)
拓展:当我们有某个业务需要用到AOP时,但又不想使用一些第三方框架,我们就可以借鉴上面的方法,定义一个特性,然后定义一个Filter,在Filter里面判断Controller等是否使用这些特性,并且特性的属性是否符合我们的需求,最后在Startup里面AddMvc时将这个Filter添加到FilterCollection里面。例如下图,自动验证AntiforgeryToken