.NET 云原生架构师训练营(权限系统 代码实现 ActionAccess)--学习笔记

 点击上方“DotNet NB”关注公众号

回复“1”获取开发者路线图

6e49660edf58c044138249a0681ab488.gif

学习分享 丨作者 / 郑 子 铭    

这是DotNet NB 公众号的第188篇原创文章

目录

  • 开发任务

  • 代码实现

开发任务

  • DotNetNB.Security.Core:定义 core,models,Istore;实现 default memory store

  • DotNetNB.Security.ActionAccess:扫描 action;添加 action authorize filter;添加集成方式

c42c43fe37437d0fffc8e12719153b38.png

代码实现

对于一个 web 项目,Filter 是在构建构建 builder 的时候添加的

builder.Services.AddControllers(options =>
{options.Filters.Add<>()
})

这里不可能让用户手动添加,所以需要有一个扩展方法给用户调用

using Microsoft.AspNetCore.Mvc;namespace DotNetNB.Security.ActionAccess
{public static class MvcOptionsExtensions{public static MvcOptions AddActionAccessControl(this MvcOptions options){options.Filters.Add<DynamicAuthorizeFilter>();return options;}}
}

创建 Resource,包含 Key 和 Data 两个属性

namespace DotNetNB.Security.Core.Models
{public class Resource{public string Key { get; set; }public object Data { get; set; }}
}

创建 ActionResource,继承 Resource,包含 ControllerName,ActionName,RouteTemplate 和 HttpVerb 几个属性

using DotNetNB.Security.Core.Models;namespace DotNetNB.Security.ActionAccess
{public class ActionResource : Resource{}public class ActionResourceData{public string? ControllerName { get; set; }public string? ActionName { get; set; }public  string DisplayName { get; set; }public string? RouteTemplate { get; set; }public string? HttpVerb { get; set; }}
}

定义一个 IResourceManager 接口,提供创建资源的方法

using DotNetNB.Security.Core.Models;namespace DotNetNB.Security.Core
{public interface IResourceManager{public Task CreateAsync(Resource resource);public Task CreateAsync(IEnumerable<Resource> resources);}
}

参考 ASP .NET Core 源码中的 ActionEndpointDataSourceBase:

https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/Routing/ActionEndpointDataSourceBase.cs

创建 endpoint 的时候有一个 action 的列表 ActionDescriptors

var endpoints = CreateEndpoints(_actions.ActionDescriptors.Items, Conventions);

它的类型是一个 IActionDescriptorCollectionProvider,专门用于扫描获取所有的 action

private readonly IActionDescriptorCollectionProvider _actions;

在 ActionAccess 模块的 ActionResourceProvider 中把它加进来

using Microsoft.AspNetCore.Mvc.Infrastructure;namespace DotNetNB.Security.ActionAccess
{public class ActionResourceProvider{private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;public ActionResourceProvider(IActionDescriptorCollectionProvider actionDescriptorCollectionProvider){_actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;}}
}

在 host 启动的时候扫描获取所有的 action 信息,定义一个 IResourceProvider 接口

namespace DotNetNB.Security.Core
{public interface IResourceProvider{public Task<IEnumerable<Resource>> ExecuteAsync();}
}

ActionResourceProvider 实现这个接口,从 ActionDescriptors 获取 action 信息,构建 ActionResourceData

public async Task<IEnumerable<Resource>> ExecuteAsync()
{var actions = _actionDescriptorCollectionProvider.ActionDescriptors.Items;var actionResources = new List<ActionResource>();foreach (var action in actions){if (action is ControllerActionDescriptor){var actionDescriptor = action as ControllerActionDescriptor;var httpMethod = action.EndpointMetadata.Where(m => m is HttpMethodMetadata).FirstOrDefault() as HttpMethodMetadata;var routeAttribute =actionDescriptor?.EndpointMetadata.FirstOrDefault(m => m is RouteAttribute) as RouteAttribute;var resourceData = new ActionResourceData();resourceData.HttpVerb = httpMethod?.HttpMethods.First();resourceData.ActionName = actionDescriptor?.ActionName;resourceData.ControllerName = actionDescriptor?.ControllerName;resourceData.RouteTemplate = routeAttribute?.Template;resourceData.DisplayName = action.DisplayName;actionResources.Add(new ActionResource(){Data = resourceData,Key = actionDescriptor.GetSecurityKey()});}}return await Task.FromResult(actionResources);
}

参考 ASP .NET Core 源码中的 AuthorizeFilter:

https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/Authorization/AuthorizeFilter.cs

AuthorizeFilter 中有一个 OnAuthorizationAsync 的方法,首先获取 policy 执行器,然后执行了认证,接着执行授权,根据授权结果修改 AuthorizationFilterContext,我们权限主要是 Forbidden 的结果,返回 403 即可

public virtual async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{if (context == null){throw new ArgumentNullException(nameof(context));}if (!context.IsEffectivePolicy(this)){return;}// IMPORTANT: Changes to authorization logic should be mirrored in security's AuthorizationMiddlewarevar effectivePolicy = await GetEffectivePolicyAsync(context);if (effectivePolicy == null){return;}var policyEvaluator = context.HttpContext.RequestServices.GetRequiredService<IPolicyEvaluator>();var authenticateResult = await policyEvaluator.AuthenticateAsync(effectivePolicy, context.HttpContext);// Allow Anonymous skips all authorizationif (HasAllowAnonymous(context)){return;}var authorizeResult = await policyEvaluator.AuthorizeAsync(effectivePolicy, authenticateResult, context.HttpContext, context);if (authorizeResult.Challenged){context.Result = new ChallengeResult(effectivePolicy.AuthenticationSchemes.ToArray());}else if (authorizeResult.Forbidden){context.Result = new ForbidResult(effectivePolicy.AuthenticationSchemes.ToArray());}
}

DynamicAuthorizeFilter 继承自 AuthorizeFilter,只获取 ControllerActionDescriptor 类型的 action,如果 permissions 中不包含 actionKey 则返回 403

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;namespace DotNetNB.Security.ActionAccess
{public class DynamicAuthorizeFilter : AuthorizeFilter{public override async Task OnAuthorizationAsync(AuthorizationFilterContext context){var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;if (actionDescriptor == null){return;}base.OnAuthorizationAsync(context);if (context.Result != null){return;}var permissions = context.HttpContext.User.Claims.Where(c => c.Type == Core.ClaimsTypes.Permission);var actionKey = actionDescriptor.GetSecurityKey();var values = permissions.Select(p => p.Value);if (!values.Contains(actionKey)){context.Result = new ForbidResult();}}}
}

在 ClaimsTypes 中增加一个 Permission 类型的 ClaimsType

namespace DotNetNB.Security.Core
{public static class ClaimsTypes{public const string Permission = "Permission";}
}

为了避免重复代码,添加一个 GetSecurityKey 的扩展方法

using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Internal;namespace DotNetNB.Security.ActionAccess;public static string GetSecurityKey(this ControllerActionDescriptor descriptor)
{var httpMethod = descriptor.EndpointMetadata.FirstOrDefault(m => m is HttpMethodMetadata) as HttpMethodMetadata;return string.Format($"{descriptor?.ControllerName}-{descriptor?.ActionName}-{httpMethod.HttpMethods.First()}");
}

这样就完成了 DotNetNB.Security.ActionAccess 模块的 ActionResourceProvider 和 DynamicAuthorizeFilter

GitHub源码链接:

https://github.com/MingsonZheng/dotnetnb.security

课程链接

.NET云原生架构师训练营讲什么,怎么讲,讲多久

推荐阅读:

《Kubernetes全栈架构师(Kubeadm高可用安装k8s集群)--学习笔记》

《.NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记》

《.NET Core开发实战(第1课:课程介绍)--学习笔记》

点击下方卡片关注DotNet NB

一起交流学习

1c0c45502082860a049f9015684f6c3e.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

表格列mouse经过时高亮显示

前几天Insus.NET有练习《表格行mouse经过时高亮显示》http://www.cnblogs.com/insus/p/3715733.html &#xff0c;今天有奇想&#xff0c;是否可以实现mouse经过表的列时&#xff0c;整列高亮呢&#xff1f;Insus.NET就在前一示例中&#xff0c;修心jQuery来练习。 修改.mouseo…

REDIS调优

2019独角兽企业重金招聘Python工程师标准>>> 1、优先使用批量操作&#xff0c;例如hset&#xff0c; 2、批量命令用管道技术 3、因为redis是单线程的防止慢命令阻塞 4、可以搭建主从读写分离集群&#xff0c;费时的操作都移到读服务 用slowlog get 查看耗时操作 转载…

分库分表下极致的优化

题外话这边说一句题外话,就是ShardingCore目前已经正式加入 NCC 开源组织了,也是希望框架和社区能发展的越来越好,希望为更多.netter提供解决方案和开源组件介绍依照惯例首先介绍本期主角:ShardingCore 一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案&#xff0c;…

关于photoshop

photoshop的常见快捷键&#xff1a;&#xff08;只写了一部分&#xff0c;还有的实用快捷键不知道&#xff09; 矩形、椭圆选框工具 M移动工具 V 套索、多边形套索、磁性套索 L 魔棒工具 W 裁剪工具 C 切片工具、切片选择工具 K 喷枪工具 J 画笔工具、铅笔工具 B 像皮图章、图案…

linux(centos) NET模式网络配置

2019独角兽企业重金招聘Python工程师标准>>> linux虚拟机一般使用桥接和net模式&#xff0c;但是由于桥接在不同的网络环境中&#xff0c;需要重新配置&#xff0c;所以建议使用net模式&#xff0c;net模式的配置步骤如下&#xff1a; 虚拟机网络连接使用NAT模式&am…

LeetCode之Island Perimeter

1、题目 You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water. Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one is…

java获取tomcat目录结构_tomcat目录结构简介_动力节点Java学院整理

tomcat目录结构简介如果我们有一个web应用&#xff0c;名称为“mail”(同时也是web应用所在目录的名称)&#xff0c;那么其目录内不同类型的文件应该服从如下放置的规则&#xff1a;一般来讲&#xff1a;对于html、jsp、css、js文件等&#xff0c;可以直接放置在web应用所在目录…

Linux和Windows下部署BeetleX服务网关

有朋友希望写一篇BeetleX服务网关部署到Linux和windows下并以服务的方式运行的介绍文章。接下详细介绍如何做并简单介绍一下网的使用。首先需要在官网(beetlex-io.com)下载对应版本的BeetleX服务网关&#xff08;现阶段只支持linux64和windows64&#xff09;&#xff0c;下载完…

HDU 1978 How many ways DP问题

How many ways Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2568 Accepted Submission(s): 1509 Problem Description这是一个简单的生存游戏&#xff0c;你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的…

课堂练习-找水王绪

题目&#xff1a;三人行设计了一个灌水论坛。信息学院的学生都喜欢在上面交流灌水&#xff0c;传说在论坛上有一个“水王”&#xff0c;他不但喜欢发帖&#xff0c;还会回复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子数目的一半。 如果你有一张当前论坛的…

java添加事件监听器_Java事件监听器的四种实现方式

自身类作为事件监听器外部类作为事件监听器匿名内部类作为事件监听器内部类作为事件监听器自身类作为事件监听器:1 import javax.swing.*;2 import java.awt.*;3 import java.awt.event.*;45 /**6 *Java事件处理机制:自身类作为事件监听器7 *authorWinty(wintysgmail.com)8 *ve…

使用Brighter实现轻量型独立管道

前言上次&#xff0c;我们介绍了使用MediatR的Behaviors功能&#xff0c;在业务层实现管道模式。(《为什么应该在业务层实现管道模式&#xff0c;而不用ASP.NET Core Middleware实现 | 2点原因和实现方式》)但是&#xff0c;这种管道有个特点或者说缺点&#xff0c;不管你需不需…

CentOS6最小化安装默认启动的服务说明

centos6.2最小化安装后执行chkconfig --list,显示所有服务&#xff0c;如下图&#xff1a;下边分别进行说明&#xff1a;auditd&#xff1a;审核守护进程当 auditd 运行的时候&#xff0c;审核信息会被发送到一个用户配置日志文件中&#xff08;默认的文件是 /var/log/audit/au…

[有奖励]GeneralUpdate开源项目招募开发者

[有奖励]GeneralUpdate开源项目招募开发者希望看到这篇文章的小伙伴&#xff0c;能看完这篇文章顺便帮忙给项目点一下“star”、转发、“在看”。先在这里谢谢各位了。github仓库地址&#xff1a;https://github.com/WELL-E/AutoUpdatergitee仓库地址&#xff1a;https://gitee…

C/C++ 读取16进制文件

1.为什么有这种需求 因为有些情况需要避免出现乱码。不管什么编码都是二进制的&#xff0c;这样表示为16进制就可以啦。 2.如何读取16进制文件 最近编程用这一问题&#xff0c;网上查了一下&#xff0c;感觉还是自己写吧。 16进制数据一般是:text0x340xb5...&#xff0c;就是0x…

基于PaddleOCR实现AI发票识别的Asp.net Core应用

简要介绍用户批量上传需要识别的照片,上传成功后,系统会启动Hangfire后台Job开始调用PaddleOCR服务返回结果,这个过程有点类似微服务的架构模型。PaddleOCRPaddleOCR是百度AI团队开源的一个项目&#xff0c;应该是目前所有免费开源OCR项目中识别效果最好的,具体可以通过PaddleO…

常用的搜索引擎dork (不断更新)

为什么80%的码农都做不了架构师&#xff1f;>>> pan.baidu.com xiaomi.rar 转载于:https://my.oschina.net/ecnu/blog/265731

学习笔记之卸载远程目标进程中的DLL模块(转)

学习笔记之卸载远程目标进程中的DLL模块 (2007-07-23 23:51:02)转载▼学习笔记之卸载远程目标进程中的DLL模块2007/7/231.首先得把DLL模块中的线程结束使用CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);创建系统线程的快照然后用Thread32First()和Thread32Next()遍历系统中所…

Wow,一个免费、不怕打的评论插件!

快速给网站添加评论功能大家好&#xff0c;我是鱼皮&#xff0c;前段时间我自己做的网站不是被 DDOS 攻击了么&#xff1f;然后我就即时地给大家分享了一下我是怎么临时 “化解” 这次 DDOS 攻击的。结果我今天一看&#xff0c;好家伙&#xff0c;这个视频竟然都已经 120 w 播放…

MSSQLSERVER启动不了,报SQL Server 无法生成 FRunCM 线程

为什么80%的码农都做不了架构师&#xff1f;>>> 在启动MSSQLSERVER服务时&#xff0c;提示启动不了&#xff0c;在事件查看器中发现报错&#xff1a;SQL Server 无法生成 FRunCM 线程 网上搜了一下说是&#xff1a;MSSQLSERVER的协议中VIA协议被启用了&#xff0c;…