ABP框架源码学习之授权逻辑
asp.net core的默认的几种授权方法参考“雨夜朦胧”的系列博客,这里要强调的是asp.net core mvc中的授权和asp.net mvc中的授权不一样,建议先看前面“雨夜朦胧”的博客。
Abp中Controller里面用到的权限验证类为:AbpMvcAuthorizeAttribute,ApplicationService里面用到的权限验证类为:AbpAuthorizeAttribute(见下图)。


AbpMvcAuthorizeAttribute和AbpAuthorizeAttribute这两个类全部继承自IAbpAuthorizeAttribute(重要!!!),下面是这两个类的源码。
namespace Abp.Authorization
{
/// <summary>
/// This attribute is used on a method of an Application Service (A class that implements <see cref="IApplicationService"/>)
/// to make that method usable only by authorized users.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AbpAuthorizeAttribute : Attribute, IAbpAuthorizeAttribute
{
/// <summary>
/// A list of permissions to authorize.
/// </summary>
public string[] Permissions { get; } /// <summary>
/// If this property is set to true, all of the <see cref="Permissions"/> must be granted.
/// If it's false, at least one of the <see cref="Permissions"/> must be granted.
/// Default: false.
/// </summary>
public bool RequireAllPermissions { get; set; } /// <summary>
/// Creates a new instance of <see cref="AbpAuthorizeAttribute"/> class.
/// </summary>
/// <param name="permissions">A list of permissions to authorize</param>
public AbpAuthorizeAttribute(params string[] permissions)
{
Permissions = permissions;
}
}
}
namespace Abp.AspNetCore.Mvc.Authorization
{
/// <summary>
/// This attribute is used on an action of an MVC <see cref="Controller"/>
/// to make that action usable only by authorized users.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AbpMvcAuthorizeAttribute : AuthorizeAttribute, IAbpAuthorizeAttribute
{
/// <inheritdoc/>
public string[] Permissions { get; set; } /// <inheritdoc/>
public bool RequireAllPermissions { get; set; } /// <summary>
/// Creates a new instance of <see cref="AbpMvcAuthorizeAttribute"/> class.
/// </summary>
/// <param name="permissions">A list of permissions to authorize</param>
public AbpMvcAuthorizeAttribute(params string[] permissions)
{
Permissions = permissions;
}
}
}
重点来啦!!!
namespace Abp.AspNetCore.Mvc.Authorization
{
public class AbpAuthorizationFilter : IAsyncAuthorizationFilter, ITransientDependency
{
public ILogger Logger { get; set; } private readonly IAuthorizationHelper _authorizationHelper;
private readonly IErrorInfoBuilder _errorInfoBuilder;
private readonly IEventBus _eventBus; public AbpAuthorizationFilter(
IAuthorizationHelper authorizationHelper,
IErrorInfoBuilder errorInfoBuilder,
IEventBus eventBus)
{
_authorizationHelper = authorizationHelper;
_errorInfoBuilder = errorInfoBuilder;
_eventBus = eventBus;
Logger = NullLogger.Instance;
} public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
// 判断context中是否有继承IAllowAnoymousFilter,有则跳出方法即验证成功
if (context.Filters.Any(item => item is IAllowAnonymousFilter))
{
return;
}
//判断是否是Controller,具体方法见下面第一张截图
if (!context.ActionDescriptor.IsControllerAction())
{
return;
} //TODO: Avoid using try/catch, use conditional checking
try
{
await _authorizationHelper.AuthorizeAsync(
context.ActionDescriptor.GetMethodInfo(),
context.ActionDescriptor.GetMethodInfo().DeclaringType
);
}
catch (AbpAuthorizationException ex)
{
Logger.Warn(ex.ToString(), ex); _eventBus.Trigger(this, new AbpHandledExceptionData(ex)); if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType))
{
context.Result = new ObjectResult(new AjaxResponse(_errorInfoBuilder.BuildForException(ex), true))
{
StatusCode = context.HttpContext.User.Identity.IsAuthenticated
? (int) System.Net.HttpStatusCode.Forbidden
: (int) System.Net.HttpStatusCode.Unauthorized
};
}
else
{
context.Result = new ChallengeResult();
}
}
catch (Exception ex)
{
Logger.Error(ex.ToString(), ex); _eventBus.Trigger(this, new AbpHandledExceptionData(ex)); if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType))
{
context.Result = new ObjectResult(new AjaxResponse(_errorInfoBuilder.BuildForException(ex)))
{
StatusCode = (int) System.Net.HttpStatusCode.InternalServerError
};
}
else
{
//TODO: How to return Error page?
context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.InternalServerError);
}
}
}
}
}




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

ABP框架源码学习之授权逻辑的更多相关文章
- ABP框架源码学习之修改默认数据库表前缀或表名称
ABP框架源码学习之修改默认数据库表前缀或表名称 1,源码 namespace Abp.Zero.EntityFramework { /// <summary> /// Extension ...
- Golang源码学习:调度逻辑(二)main goroutine的创建
接上一篇继续分析一下runtime.newproc方法. 函数签名 newproc函数的签名为 newproc(siz int32, fn *funcval) siz是传入的参数大小(不是个数):fn ...
- 集合框架源码学习之ArrayList
目录: 0-0-1. 前言 0-0-2. 集合框架知识回顾 0-0-3. ArrayList简介 0-0-4. ArrayList核心源码 0-0-5. ArrayList源码剖析 0-0-6. Ar ...
- CI框架源码学习笔记1——index.php
做php开发一年多了,陆陆续续用过tp/ci/yii框架,一直停留在只会使用的层面上,关于框架内部的结构实际上是不甚了解的.为了深入的学习,决定把CI框架的源码从头到尾的学习一下, 主要因为CI框架工 ...
- axel源码学习(0)——程序逻辑
axel简介 axel是一个命令行下的轻量级http/ftp 下载加速工具,支持多线程下载和断点续传,支持从多个镜像下载同一文件. axel的用法如下: 图 0.1 axel usage axel 粗 ...
- 集合框架源码学习之HashMap(JDK1.8)
目录: 0-1. 简介 0-2. 内部结构分析 0-2-1. JDK18之前 0-2-2. JDK18之后 0-3. LinkedList源码分析 0-3-1. 构造方法 0-3-2. put方法 0 ...
- 集合框架源码学习之LinkedList
0-1. 简介 0-2. 内部结构分析 0-3. LinkedList源码分析 0-3-1. 构造方法 0-3-2. 添加add方法 0-3-3. 根据位置取数据的方法 0-3-4. 根据对象得到索引 ...
- CI框架源码学习笔记7——Utf8.php
愉快的清明节假期结束了,继续回到CI框架学习.这一节我们来看看Utf8.php文件,它主要是用来做utf8编码,废话不多说,上代码. class CI_Utf8 { /** * Class const ...
- CI框架源码学习笔记2——Common.php
上一节我们最后说到了CodeIgniter.php,可是这一节的标题是Common.php,有的朋友可能会觉得很奇怪.事实上,CodeIgniter.php其实包含了ci框架启动的整个流程. 里面引入 ...
随机推荐
- C#中的基元类型、值类型和引用类型
C# 中的基元类型.值类型和引用类型 1. 基元类型(Primitive Type) 编译器直接支持的类型称为基元类型.基元类型可以直接映射到 FCL 中存在的类型.例如,int a = 10 中的 ...
- K8S API 调用
不好意,本人比较懒,OneNote 复制粘贴的时候就是自动变成图片了.请各位看官多多见谅. 遗留问题: 目前pod仅支持修改 * and(),so...
- Python判断文件是否存在的三种方法【转】
转:http://www.cnblogs.com/jhao/p/7243043.html 通常在读写文件之前,需要判断文件或目录是否存在,不然某些处理方法可能会使程序出错.所以最好在做任何操作之前,先 ...
- python 函数返回多个参数的赋值方法
#定义函数 def Get_Counter_AllMeasureValue(self, inst_dg_address): """ get all measure val ...
- 基于jQuery表单快速录入数据功能
一.功能介绍:完全依靠jQuery,表单table新增行(按键盘tab增一行,按esc删一行),也可以加一个新增行按钮点击新增多行,这里就不多说了~~ 二.该功能主要实现技术: 1,总体.NET MV ...
- lambda高级进阶--延迟执行
前面的整理我们也已经说到了,使用lambda表达式的主要原因是,将代码的执行延迟到一个合适的时间点.在使用lambda表达式的时候务必记住一点就是说lambda表达式都是延迟执行的. 延迟执行代码的原 ...
- POI--HSSFSheet类
用POI来作成一个Sheet,可以用「HSSFSheet」类,该类构造器如下: 新建Sheet 从构造器可以看出,虽然它有两个构建器,但都是protected的,所以要新建Sheet,只能通过Work ...
- 定时任务schedule(spring boot )
1. 定时任务实现方式:SpringBoot自带的Scheduled,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多,本文主要介绍. 执行方式:单线程(串行)多线程(并行) ...
- PHP中利用PHPMailer配合QQ邮箱实现发邮件
PHPMailer的介绍: 优点: 可运行在任何平台之上 支持SMTP验证 发送邮时指定多个收件人,抄送地址,暗送地址和回复地址:注:添加抄送.暗送仅win平台下smtp方式支持 支持多种邮件编码包括 ...
- The mkdir Command
The mkdir command is is used to create new directories. A directory, referred to as a folder in some ...