前言

目前公司采用的开发框架是ABP VNext微服务框架

最近突然发现一个问题,ABP中如果控制器或服务层没有加 Authorize特性的话,则不会走身份认证,且不会认证Token

如图:

但是项目已开发大半,一个个去补Authorize特性,工作量比较大,也容易产生遗漏

就想着以前做单体应用的时候,有个全局添加特性的方法,也就是如下代码:

Services.AddMvc(setupAction =>
{
setupAction.Filters.Add<AuthorizeFilter>();
});

本以为这样就万事大吉了,没想到还有坑在里面..

我们都知道,ABP提供了服务间的动态API通讯功能,它的原理是先获取对应服务的描述,然后通过描述来访问对应的服务节点,

也就是 api/abp/api-definition 这个描述JSON

我们用以上的代码添加了全局授权之后会发现api-definition也被权限管控了,由于api-definition是由ABP框架自动生成的,我们也无法在这个终结点上添加类似  AllowAnonymous 的过滤特性

正文

那么应该如何解决这个问题呢?

首先想到的就是实现自己的授权特性,只需要继承 IAsyncAuthorizationFilter,即可

但是如果采用自己的AuthorizationFilter,则需要重写整个 OnAuthorizationAsync 事件.

ABP提供了角色之类的授权信息就都需要自行重写.

后来想到,可以继承AuthorizeFilter ,添加我们想要的过滤之后直接执行父类的方法,说干就干,我们继承AuthorizeFilter ,代码实现如下:

    public class AbpAuthorizeFilter : AuthorizeFilter
{ public AbpAuthorizeFilter()
: base()
{
} public override Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
//过滤动态API
if (context.HttpContext.Request.Path.Value.EndsWith("/api-definition"))
{
return Task.CompletedTask;
}
return base.OnAuthorizationAsync(context);
} }

可是当我们信心满满的把这个拦截器注入之后,会发现整个授权管道,压根就不走自己的这个重写方法.

找了很多资料,最终在官方的issues中找到了类似的疑问,Overrided OnAuthorizationAsync function from AuthorizeFilter can't work in customer class. · Issue #30025 · dotnet/aspnetcore (github.com)

是因为在.NET 5.0 之后,AuthorizeFilter继承了 IFilterFactory,所以在生成实例的时候其实是来自于IFilterFactory的CreateInstance方法, 我们没有重写这个方法,所以一直产生的还是AuthorizeFilter 实例

我们修改代码如下:

    public class AbpAuthorizeFilter2 : AuthorizeFilter
{ public AbpAuthorizeFilter2()
: base()
{
} public override Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
//过滤动态API
if (context.HttpContext.Request.Path.Value.EndsWith("/api-definition"))
{
return Task.CompletedTask;
}
return base.OnAuthorizationAsync(context);
} IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return this;
}
}

运行后发现,在执行到这个拦截器的时候,就会报错,提示PolicyProvider 不能为空.  这就很纳闷了,最终选择去查看一下AuthorizeFilter的源码,aspnetcore/src/Mvc/Mvc.Core/src/Authorization/AuthorizeFilter.cs at 1bda10b33b6cc6f3bbaceabbadb4ddd18ca6e68e · dotnet/aspnetcore (github.com)

我们发现他这个PolicyProvider对象来自于IOC容器,且在CreateInstance方法中判断了这个类是否为空,如果为空则返回基类自己,代码如下:

IFilterMetadata IFilterFactory.CreateInstance(IServiceProvider serviceProvider)
{
if (Policy != null || PolicyProvider != null)
{
// The filter is fully constructed. Use the current instance to authorize.
return this;
} Debug.Assert(AuthorizeData != null);
var policyProvider = serviceProvider.GetRequiredService<IAuthorizationPolicyProvider>();
return AuthorizationApplicationModelProvider.GetFilter(policyProvider, AuthorizeData);
}

那我们就好办了,直接从IOC容器中拿到IAuthorizationPolicyProvider这个实现类,提供给基类即可,我们修改代码如下:

    public class AbpAuthorizeFilter:AuthorizeFilter
{ public AbpAuthorizeFilter(IServiceProvider serviceProvider)
: base(policyProvider: serviceProvider.GetRequiredService<IAuthorizationPolicyProvider>(), authorizeData: new[] { new AuthorizeAttribute() })
{
}
public void OnAuthorization(AuthorizationFilterContext context)
{
OnAuthorizationAsync(context);
} public override Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
//过滤动态API
if (context.HttpContext.Request.Path.Value.EndsWith("/api-definition"))
{
return Task.CompletedTask;
}
return base.OnAuthorizationAsync(context);
} }

然后修改HostModule中全局授权的方法如下(.NETCORE 是Startup)

context.Services.AddMvc(setupAction =>
{
//添加自定义的全局拦截器
setupAction.Filters.Add<AbpAuthorizeFilter>(); });

至此,我们就完成了过滤abp的描述控制器的工作.

后记

碰到奇葩问题,多看看官方源码还是有好处的,有些实现并不是想当然的东西,还是需要实践

ABP VNext添加全局认证(如何继承AuthorizeFilter)的更多相关文章

  1. [Abp vNext 源码分析] - 2. 模块系统的变化

    一.简要说明 本篇文章主要分析 Abp vNext 当中的模块系统,从类型构造层面上来看,Abp vNext 当中不再只是单纯的通过 AbpModuleManager 来管理其他的模块,它现在则是 I ...

  2. ABP VNext框架基础知识介绍(1)--框架基础类继承关系

    在我较早的时候,就开始研究和介绍ABP框架,ABP框架相对一些其他的框架,它整合了很多.net core的新技术和相关应用场景,虽然最早开始ABP框架是基于.net framework,后来也全部转向 ...

  3. [Abp vNext微服务实践] - 添加中文语言

    简介 abp vNext中提供了多语言功能,默认语言是英文,没有提供中文语言包.在业务开发中,定义权限后需要用中文的备注提供角色选择,本篇将介绍如何在abp vNext中加入中文语言. step1:添 ...

  4. [Abp vNext 源码分析] - 7. 权限与验证

    一.简要说明 在上篇文章里面,我们在 ApplicationService 当中看到了权限检测代码,通过注入 IAuthorizationService 就可以实现权限检测.不过跳转到源码才发现,这个 ...

  5. [Abp vNext 源码分析] - 11. 用户的自定义参数与配置

    一.简要说明 文章信息: 基于的 ABP vNext 版本:1.0.0 创作日期:2019 年 10 月 23 日晚 更新日期:暂无 ABP vNext 针对用户可编辑的配置,提供了单独的 Volo. ...

  6. [Abp vNext 源码分析] - 5. DDD 的领域层支持(仓储、实体、值对象)

    一.简要介绍 ABP vNext 框架本身就是围绕着 DDD 理念进行设计的,所以在 DDD 里面我们能够见到的实体.仓储.值对象.领域服务,ABP vNext 框架都为我们进行了实现,这些基础设施都 ...

  7. [Abp vNext 源码分析] - 14. EntityFramework Core 的集成

    一.简要介绍 在以前的文章里面,我们介绍了 ABP vNext 在 DDD 模块定义了仓储的接口定义和基本实现.本章将会介绍,ABP vNext 是如何将 EntityFramework Core 框 ...

  8. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(一)

    系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...

  9. [Abp vNext 源码分析] - 21. 界面与文字的本地化

    一.简介 ABP vNext 提供了全套的本地化字符串支持,具体用法可以参考官方使用文档.vNext 本身是对 Microsoft 提供的本地化组件进行了实现,通过 JSON 文件提供本地化源,这一点 ...

  10. 源码解析-Abp vNext丨LocalEventBus

    前言 基础篇已经更新完了,从本篇开始我们进入,中级篇(学习部分源代码)我会挑一些我个人认为比较重要的知识点结合部分开源项目进行源码讲解,咱们废话不说直接上车. Abp vNext的事件总线分2种,一种 ...

随机推荐

  1. GraalVM(云原生时代的Java)和IoT在边缘侧落地与实践

    环顾四周,皆是对手! 云时代的掉队者,由于Java启动的高延时.对资源的高占用.导致在Serverless及FaaS架构下力不从心,在越来越流行的边缘计算.IoT方向上也是难觅踪影; Java语言在业 ...

  2. Gradio入门到进阶全网最详细教程[二]:快速搭建AI算法可视化部署演示(侧重参数详解和案例实践)

    Gradio入门到进阶全网最详细教程[二]:快速搭建AI算法可视化部署演示(侧重参数详解和案例实践) 相关文章:Gradio入门到进阶全网最详细教程[一]:快速搭建AI算法可视化部署演示(侧重项目搭建 ...

  3. Spring 之bean的生命周期

    文章目录 IOC Bean的生命周期 运行结果 实例演示 实体类 实例化前后置代码 初始化的前后置代码 application.xml 总结 今天我们来聊一下Spring Bean的生命周期,这是一个 ...

  4. Pwn系列之Protostar靶场 Stack6题解

    源码如下: #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <stri ...

  5. 2022-12-30:某天小美进入了一个迷宫探险,根据地图所示,这个迷宫里有无数个房间 序号分别为1、2、3、...入口房间的序号为1 任意序号为正整数x的房间,都与序号 2*x 和 2*x + 1

    2022-12-30:某天小美进入了一个迷宫探险,根据地图所示,这个迷宫里有无数个房间 序号分别为1.2.3.-入口房间的序号为1 任意序号为正整数x的房间,都与序号 2x 和 2x + 1 的房间之 ...

  6. 2022-04-26:给定四个整数 sx , sy ,tx 和 ty,如果通过一系列的转换可以从起点 (sx, sy) 到达终点 (tx, ty),则返回 true,否则返回 false。 从点 (x

    2022-04-26:给定四个整数 sx , sy ,tx 和 ty,如果通过一系列的转换可以从起点 (sx, sy) 到达终点 (tx, ty),则返回 true,否则返回 false. 从点 (x ...

  7. 2022-03-29:整个二维平面算是一张地图,给定[x,y],表示你站在x行y列, 你可以选择面朝的任何方向, 给定一个正数值angle,表示你视野的角度为, 这个角度内你可以看无穷远,这个角度外你

    2022-03-29:整个二维平面算是一张地图,给定[x,y],表示你站在x行y列, 你可以选择面朝的任何方向, 给定一个正数值angle,表示你视野的角度为, 这个角度内你可以看无穷远,这个角度外你 ...

  8. ModuleNotFoundError: No module named 'flask_sqlalchemy'

    ModuleNotFoundError: No module named 'flask_sqlalchemy' 解决: pip install flask_sqlalchemy

  9. HINT: Add or change a related_name argument to the definition for 'usersApp.

    错误原因是你的项目使用的不是Django自带的用户表,采用的自定义的用户表,这个时候需要在settings.py里面进行指定. AUTH_USER_MODEL = 'usersApp.UserProf ...

  10. MD5加密后为0e开头的字符串

    QNKCDZO         0e830400451993494058024219903391 s878926199a      0e545993274517709034328855841020 s ...