目录

  • 开发任务
  • 代码实现

开发任务

  • 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) 。

最新文章

  1. unity 内存中切割图片
  2. .NET破解之google瓦片下载及拼接
  3. sqlserver中表变量和变量表之间区别
  4. Linux远程管理
  5. 动态规划(区间DP):HDU 5115 Dire Wolf
  6. bash:command not found
  7. perl6 JSON::Fast模块json解析的使用
  8. LED音乐频谱之输出数据处理
  9. Git Workflow简介
  10. The SSL certificate used to load resources from xxx will be distrusted in M70.
  11. Jetty 嵌入式启动官方完整教程
  12. python之验证码识别 特征向量提取和余弦相似性比较
  13. Servlet(4)—一个简单的Servlet实例
  14. Linux惊群效应详解
  15. javaScript真值和假值以及相等操作符
  16. Wannafly挑战赛9 D - 造一造
  17. App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure.
  18. vue 缓存的keepalive页面刷新数据
  19. ADO之command
  20. Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 Part 3 (by TAISEER)

热门文章

  1. 不用find,怎样递归地给目录设置700,给文件设置600权限?
  2. js 将数字型 的字符串 转 数字 【整数 /浮点型数字】
  3. 使用 navigator.userAgent.toLowerCase() 区别 浏览器 类型
  4. springboot集成oss阿里云存储
  5. 帮你克服web字体选择焦虑症
  6. 你的Kubernetes Java应用优雅停机了吗?
  7. Servlet虚拟路径匹配规则
  8. C++与lua交互之C++访问lua
  9. 使用 electron 和 electron-forge 加载 本地磁盘资源 img 的问题
  10. 火山引擎MARS-APM Plus x 飞书 |降低线上OOM,提高App性能稳定性