一.问题

最近收到一位朋友的求助,说他项目上的权限授权出现了问题,现象是在基础服务授权角色:RC 权限:X.Default,在基础服务使用RC角色的用户登录能访问到权限X.Default资源,而在X服务访问不到。重启X服务后就可以访问。

项目框架:ABP Vnext 6.0版本

数据库:共享一个

微服务架构如下:

 
 

请求/api/abp/application-configuration接口

基础服务

"auth": {
"Policies": {
"X.Default": true
}
"grantedPolicies": {
"X.Default": true
}
},

X服务

"auth": {
"Policies": {
"X.Default": true
}
"grantedPolicies": {
}
},

二.分析原因

1.X服务权限资源已加载,没有获取到x.Default的授权

2.基础服务权限资源已加载并且获取到x.Default的授权

3.共享库AbpPermissionGrants表中存在记录:ProviderKey:R  ProviderName:RX  Name: x.Default。 说明该角色已经授权了X.Default

4.重启X服务后再次请求获取到X.Default的授权

由上可推测X服务获取不到X.Default授权的原因大概是因为缓存。

怎么验证猜测,把日志等级调为Debug,再次请求查看日志

2023-06-15 11:14:53.087 +08:00 [DBG] PermissionStore.GetCacheItemAsync: pn:RX,pk:R,n:X.Default......
2023-06-15 11:14:53.088 +08:00 [DBG] Found in the cache: pn:RX,pk:R,n:X.Default......

猜对了。

三.问题本质

要了解问题本质我们先来简单梳理一遍权限授权验证流程

不管是走中间件还是拦截器,验证授权最终都是调用了AbpAuthrizaionService.AuthorzieAsync()方法,结合日志,我们来看看PermissionStore.IsGrantedAsync()方法

public virtual async Task<bool> IsGrantedAsync(string name, string providerName, string providerKey)
{
return (await GetCacheItemAsync(name, providerName, providerKey)).IsGranted;
} protected virtual async Task<PermissionGrantCacheItem> GetCacheItemAsync(
string name, // X.Default
string providerName, // RX
string providerKey) //R
{
var cacheKey = CalculateCacheKey(name, providerName, providerKey); //计算缓存key=pn:RX,pk:R,n:X.Default Logger.LogDebug($"PermissionStore.GetCacheItemAsync: {cacheKey}"); var cacheItem = await Cache.GetAsync(cacheKey); //获取缓存 if (cacheItem != null)
{
Logger.LogDebug($"Found in the cache: {cacheKey}");
return cacheItem; //存在则返回
} Logger.LogDebug($"Not found in the cache: {cacheKey}"); cacheItem = new PermissionGrantCacheItem(false); await SetCacheItemsAsync(providerName, providerKey, name, cacheItem); //不存在缓存则查数据库后将结果缓存 return cacheItem;
}
 protected virtual async Task SetCacheItemsAsync(
string providerName,
string providerKey,
string currentName,
PermissionGrantCacheItem currentCacheItem)
{
var permissions = PermissionDefinitionManager.GetPermissions(); //获取该服务加载的权限资源 Logger.LogDebug($"Getting all granted permissions from the repository for this provider name,key: {providerName},{providerKey}"); var grantedPermissionsHashSet = new HashSet<string>(
(await PermissionGrantRepository.GetListAsync(providerName, providerKey)).Select(p => p.Name) //从数据库查找已授权的权限资源
); Logger.LogDebug($"Setting the cache items. Count: {permissions.Count}"); var cacheItems = new List<KeyValuePair<string, PermissionGrantCacheItem>>(); //权限授权结果缓存集合 foreach (var permission in permissions)
{
var isGranted = grantedPermissionsHashSet.Contains(permission.Name); //存在授权列表中则已授权,否则未授权 cacheItems.Add(new KeyValuePair<string, PermissionGrantCacheItem>( //把结果加进集合
CalculateCacheKey(permission.Name, providerName, providerKey),
new PermissionGrantCacheItem(isGranted))
); if (permission.Name == currentName)
{
currentCacheItem.IsGranted = isGranted;
}
} await Cache.SetManyAsync(cacheItems); //设置缓存 Logger.LogDebug($"Finished setting the cache items. Count: {permissions.Count}");
}

第一次请求X服务:load了一遍权限资源,并把X.Default标记为false缓存了起来,后面再授权角色RX 资源X.Default,因为缓存的存在再次获取还是未授权。重启服务后正常

而基础服务之所以能实时更新是因为权限管理模型就在这里, PermissionGrantCacheItemInvalidator 订阅了PermissionGrant变更的本地事件会清空缓存。

四.解决方案

一.授权验证都走基础服务

1.引用Volo.Abp.AspNetCore.Mvc.Client nutget包

2.添加AbpAspNetCoreMvcClientModule模块

3.添加配置

"RemoteServices": {
"AbpMvcClient": {
"BaseUrl": "http://localhost:XXXX", //配基础服务或网关
}
}

RemotePermissionChecker会取代PermissionChecker,请求远程服务进行权限验证,并将结果缓存起来,有效时间是300s(硬编码,todo:未来可配)

  configuration = await Cache.GetOrAddAsync(
cacheKey,
async () => await ApplicationConfigurationAppService.GetAsync(),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300) //TODO: Should be configurable.
}
);

更改后的授权验证流程

二 使用Redis缓存替换应用缓存

备注:key要一致

最后朋友采用了方案二解决了问题,理由是实时。如果你有更好的解决方案请在评论告知我感谢!!!!

关于Abp Vnext 权限授权的问题的更多相关文章

  1. Abp.vNext 权限备注

    Abp 内部是基于 asp.net core 基于 策略的  授权方式,每个权限为一个策略 权限分为: 1.定义权限(先定义权限组,后添加权限),每个模块都应该创建一个PermissionDefini ...

  2. Abp VNext权限定义

    在Shop.Application.Contracts项目中Permissions目录下ShopPermissions定义权限名 namespace Shop.Permissions { public ...

  3. [Abp vNext微服务实践] - 前后端分类

    一.前景 abp vNext是ABP 开源 Web应用程序框架,是abp的新一代开源web框架.框架完美的集成.net core.identity server4等开源框架,适用于构建web应用程序和 ...

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

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

  5. abp vnext 开发快速入门 3 实现权限控制

    上篇讲了abp vnext 实现了简单的增加操作的例子.删除更新查询基本类似,这里就不讲了,接下来说下如何实现角色权限控制. 再说之前,先说下如果想更加透彻的理解abp vnext的权限控制,最好是先 ...

  6. ABP vNext微服务架构详细教程——分布式权限框架

    1.简介 ABP vNext框架本身提供了一套权限框架,其功能非常丰富,具体可参考官方文档:https://docs.abp.io/en/abp/latest/Authorization 但是我们使用 ...

  7. 使用Abp vnext构建基于Duende.IdentityServer的统一授权中心(一)

    原来看到很多示例都是基于IdentityServer4的统一授权中心,但是IdentityServer4维护到2022年就不再进行更新维护了,所以我选择了它的升级版Duende.IdentitySer ...

  8. ABP VNext框架中Winform终端的开发和客户端授权信息的处理

    在ABP VNext框架中,即使在它提供的所有案例中,都没有涉及到Winform程序的案例介绍,不过微服务解决方案中提供了一个控制台的程序供了解其IDS4的调用和处理,由于我开发过很多Winform项 ...

  9. [Abp vNext微服务实践] - 服务通讯

    简介 服务通讯是微服务架构中必不可少的功能,服务通讯的效率决定了微服务架构的优略.常用的微服务通讯策略有两种,分别是rpc.http,其中rpc以gRpc框架为代表使用者最多.abp vNext微服务 ...

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

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

随机推荐

  1. Kubernetes(K8S)内核优化常用参数详解

    net.ipv4.tcp_keepalive_time=600 net.ipv4.tcp_keepalive_intvl=30 net.ipv4.tcp_keepalive_probes=10 net ...

  2. 京东LBS推荐算法实践

    作者:京东零售 郑书剑 1.推荐LBS业务介绍 1.1 业务场景 现有的同城购业务围绕京东即时零售能力搭建了到店.到家两种业务场景.同城业务与现有业务进行互补,利用高频,时效性快的特点,可以有效提升主 ...

  3. python之zipfile应用

    zipfile Python 中 zipfile 模块提供了对 zip 压缩文件的一系列操作. 1 f=zipfile.ZipFile("test.zip",mode=" ...

  4. Git提交代码仓库的两种方式

    目录 一: 两种本地与远程仓库同步 1 git 远程仓库 提交本地版本库操作 提交到远程版本库操作 1.Git 全局设置: 2.增加一个远程仓库地址 3.查询当前存在的远程仓库 5.本地版本库内容提交 ...

  5. 企业应用可观测性利器!华为云CodeArts APM发布

    摘要:近日,华为云全链路应用性能管理服务CodeArts APM全新上线,提供端到端的全链路性能管理服务,涵盖前端监控.应用性能监控,全面拥抱开源生态. 本文分享自华为云社区<企业应用可观测性利 ...

  6. vue中获取所有路由

    在router实例上有options属性:

  7. csp-s2022游记

    ## 10.29### 民间数据:洛谷 $95+85+60+44=284$  infoj $90+40+40+44=214$  **输麻了**### 赛时经历开考前发现前面坐着 Qiuly,好可怕.开 ...

  8. flink HelloWorld 之词频统计

    最近也在跟着学习flink,也是费了一点功夫才把开发环境都搭建了起来,做了一个简单的词频统计的demo- 准备工作 首先我们需要搭建需要的flink开发环境,我这里使用的是IDEA作为我的开发工具,所 ...

  9. Java中数字相关的类有哪些?Nuber数字类和Math数学类详解

    前言 我们在解决实际问题时,会经常对数字.日期和系统设置进行处理,比如在我们的代码中,经常会遇到一些数字&数学问题.随机数问题.日期问题和系统设置问题等. 为了解决这些问题,Java给我们提供 ...

  10. Prism Sample 14-UsingEventAggregator

    这次是事件聚合器的应用. 事件聚合器应用第一步:定义一个事件聚合器,应该是一个可访问的公共区域,例14为它做了一个core的项目.代码很简单: using Prism.Events; namespac ...