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

博客 分享
0 258
张三
张三 2022-02-16 22:55:26
悬赏:0 积分 收藏

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

目录

  • 开发任务
  • 代码实现

开发任务

  • DotNetNB.Security.Core:定义 core,models,Istore;实现 default memory store
  • DotNetNB.Security.EntityAccess:扫描 entities;添加 ef savechanges interceptor

代码实现

我们现在已经通过 ActionResourceProvider 完成了 action 的扫描,生成了 ResourceModel,需要持久化到 IResourceStore,持久化之后才可以将它们绑定到用户,角色

由于 ActionAccess 是一个类库,提供了一些比较零散的功能,所以需要添加一个扩展方法把功能组装起来,在 host 启动的时候执行 action 的扫描

using Microsoft.Extensions.DependencyInjection;namespace DotNetNB.Security.Core.Extensions{    public static class ServiceCollectionExtensions    {        public static IServiceCollection AddSecurity(this IServiceCollection services)        {            services.AddHostedService<ResourceProviderHostedService>();            return services;        }    }}

ResourceProviderHostedService 继承自 IHostedService,有一个 StartAsync 和一个 StopAsync 方法

using Microsoft.Extensions.Hosting;namespace DotNetNB.Security.Core{    public class ResourceProviderHostedService : IHostedService    {        public async Task StartAsync(CancellationToken cancellationToken)        {        }        public async Task StopAsync(CancellationToken cancellationToken)        {        }    }}

新建一个示例的 api 项目 DotNetNB.WebApplication,在这个 api 项目里面使用我们的 dll 要足够简单,就像使用 asp .net core 的 api 一样

添加 DotNetNB.Security.Core 的项目引用之后,可以直接在 Program.cs 中调用扩展方法

using DotNetNB.Security.Core.Extensions;...builder.Services.AddSecurity();

在启动扫描的时候,Security.Core 并不知道外部的 host 里面有哪些 action provider,所以需要注册进来,需要构建一个 builder

同时需要一个配置 options 告诉我们它是来自哪个包,是 ActionAccess,还是 EntityAccess

参照 MvcOptions

builder.Services.AddControllers(options => {});

它是一个 Action 的委托

public static IMvcBuilder AddControllers(  this IServiceCollection services,  Action<MvcOptions>? configure){  IMvcCoreBuilder builder = services != null ? MvcServiceCollectionExtensions.AddControllersCore(services) : throw new ArgumentNullException(nameof (services));  if (configure != null)    builder.AddMvcOptions(configure);  return (IMvcBuilder) new MvcBuilder(builder.Services, builder.PartManager);}

于是乎我们在 AddSecurity 添加一个入参

public static IServiceCollection AddSecurity(this IServiceCollection services, Action<SecurityOption>? configure)

SecurityOption

using Microsoft.Extensions.DependencyInjection;namespace DotNetNB.Security.Core.Extensions{    public class SecurityOption    {        public IServiceCollection Services { get; set; }    }}

在调用 AddSecurity 扩展方法的时候通过 SecurityOption 进行配置,这样所有对外的 api 只需要做这一个配置就可以把两个包的所有功能引用进去

builder.Services.AddSecurity(options =>{    options.AddActionAccess();    options.AddEntityAccess<DBContext>();});

参考 MvcCoreServiceCollectionExtensions 的 AddMvcCoreServices 方法

internal static void AddMvcCoreServices(IServiceCollection services){    //    // Options    //    services.TryAddEnumerable(        ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, MvcCoreMvcOptionsSetup>());        ...}

在 ActionAccess 中添加一个扩展方法 AddActionAccessControl,将 IResourceProvider 添加进去,这样就可以在 ResourceProviderHostedService 中读取到

using DotNetNB.Security.Core;using DotNetNB.Security.Core.Extensions;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.DependencyInjection.Extensions;namespace DotNetNB.Security.ActionAccess{    public static class SecurityOptionExtensions    {        public static SecurityOption AddActionAccessControl(this SecurityOption option)        {            option.Services.TryAddEnumerable(ServiceDescriptor.Transient<IResourceProvider, ActionResourceProvider>());            return option;        }    }}

在 ResourceProviderHostedService 的构造函数中读取 IServiceProvider

using Microsoft.Extensions.Hosting;namespace DotNetNB.Security.Core{    public class ResourceProviderHostedService : IHostedService    {        private readonly IServiceProvider[] _serviceProviders;        public ResourceProviderHostedService(IServiceProvider[] serviceProviders)        {            _serviceProviders = serviceProviders;        }        public async Task StartAsync(CancellationToken cancellationToken)        {        }        public async Task StopAsync(CancellationToken cancellationToken)        {        }    }}

在 EntityAccess 中同样添加一个扩展方法 AddEntityAccessControl

using DotNetNB.Security.Core;using DotNetNB.Security.Core.Extensions;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.DependencyInjection.Extensions;namespace DotNetNB.Security.EntityAccess{    public static class SecurityOptionExtensions    {        public static SecurityOption AddEntityAccessControl(this SecurityOption option)        {            option.Services.TryAddEnumerable(ServiceDescriptor.Transient<IResourceProvider, EntityResourceProvider>());            return option;        }    }}

EntityResourceProvider 继承 IResourceProvider

using DotNetNB.Security.Core;using DotNetNB.Security.Core.Models;namespace DotNetNB.Security.EntityAccess{    public class EntityResourceProvider : IResourceProvider    {        public async Task<IEnumerable<Resource>> ExecuteAsync()        {            return new List<Resource>();        }    }}

完成之后在 DotNetNB.WebApplication 中添加项目引用,就可以进行配置

builder.Services.AddSecurity(options =>{    options.AddActionAccessControl()        .AddEntityAccessControl();});

后面再完善 AddEntityAccessControl 加入 DBContext

GitHub源码链接:

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

课程链接

https://appsqsyiqlk5791.h5.xiaoeknow.com/v1/course/video/v_5f39bdb8e4b01187873136cf?type=2

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

posted @ 2022-02-16 22:10 MingsonZheng 阅读(1) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员