前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET 云原生架构师训练营(权限系统 代码实现 Store.EntityFramework)--学习笔记

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

原创
作者头像
郑子铭
修改2022-02-24 10:08:41
2030
修改2022-02-24 10:08:41
举报

目录

  • 开发任务
  • 代码实现

开发任务

  • DotNetNB.Security.Core:定义 core,models,Istore;实现 default memory store
  • DotNetNB.Security.Store.EntityFramework:基于 mysql 创建 PermissionStore 和 ResourceStore
image.png
image.png

代码实现

我们需要在 ResourceProviderHostedService 中读取所有的 Resource,将 Resource 转换为 Permission,再将 Permission 分配给 Role

创建 Permission 的 model

代码语言:txt
复制
namespace DotNetNB.Security.Core.Models
{
    public class Permission
    {
        public string Key { get; set; }

        public string DisplayName { get; set; }

        public string Description { get; set; }

        public IEnumerable<Resource> Resources { get; set; }
    }
}

在 IPermissionManager 接口中定义 CreateAsync 方法

代码语言:txt
复制
namespace DotNetNB.Security.Core
{
    public interface IPermissionManager
    {
        public Task CreateAsync(string key, string displayName, string description, IEnumerable<string> resources);
    }
}

IResourceManager 接口添加通过 key 获取 resource 的方法 GetByKeysAsync

代码语言:txt
复制
public Task<IEnumerable<Resource>> GetByKeysAsync(IEnumerable<string> resources);

PermissionManager 里面需要用到 Store,先定义接口 IPermissionStore

代码语言:txt
复制
using DotNetNB.Security.Core.Models;

namespace DotNetNB.Security.Core.Store
{
    public interface IPermissionStore
    {
        public Task CreateAsync(Permission permission);
    }
}

在 PermissionManager 里面创建一个 permission,通过 ResourceManager 获取到所有 resources 赋值给 permission,再将 permission 存储到 PermissionStore

代码语言:txt
复制
using DotNetNB.Security.Core.Models;
using DotNetNB.Security.Core.Store;

namespace DotNetNB.Security.Core;

public class PermissionManager: IPermissionManager
{
    private readonly IResourceManager _resourceManager;
    private readonly IPermissionStore _permissionStore;

    public PermissionManager(IResourceManager resourceManager, IPermissionStore permissionStore)
    {
        _resourceManager = resourceManager;
        _permissionStore = permissionStore;
    }

    public async Task CreateAsync(string key, string displayName, string description, IEnumerable<string> resourceKeys)
    {
        if (string.IsNullOrEmpty(key))
            throw new ArgumentNullException(nameof(key));

        var permission = new Permission { Key = key, DisplayName = displayName, Description = description };
        var resources = await _resourceManager.GetByKeysAsync(resourceKeys);
        permission.Resources = resources;

        await _permissionStore.CreateAsync(permission);
    }
}

创建 DefaultPermissionStore 实现 IPermissionStore

代码语言:txt
复制
using DotNetNB.Security.Core.Models;

namespace DotNetNB.Security.Core.Store
{
    public class DefaultPermissionStore : IPermissionStore
    {
        private List<Permission> _list;

        public DefaultPermissionStore()
        {
            _list = new List<Permission>();
        }

        public async Task CreateAsync(Permission permission)
        {
            _list.Add(permission);
        }
    }
}

IPermissionStore 接口添加获取 permission 列表的方法

代码语言:txt
复制
public Task<IEnumerable<Permission>> GetAllAsync();

在 DefaultPermissionStore 中直接将列表返回即可

代码语言:txt
复制
public async Task<IEnumerable<Permission>> GetAllAsync()
{
    return _list;
}

在 PermissionManager 中通过 PermissionStore 获取 Permission 列表返回

代码语言:txt
复制
public async Task<IEnumerable<Permission>> GetAllAsync()
{
    return await _permissionStore.GetAllAsync();
}

在 IPermissionStore 中添加 GetByKeyAsync 方法,在 PermissionManager 中用于校验 key 是否存在对应的 Permission

代码语言:txt
复制
public Task<Permission> GetByKeyAsync(string key);

在 DefaultPermissionStore 中实现 GetByKeyAsync 方法

代码语言:txt
复制
public async Task<Permission> GetByKeyAsync(string key)
{
    return _list.SingleOrDefault(r => r.Key == key);
}

在 PermissionManager 中校验 key 是否存在对应的 Permission

代码语言:txt
复制
var origin = await _permissionStore.GetByKeyAsync(key);
if (origin != null)
    throw new InvalidOperationException("Duplicated permission key found");

IResourceManager 接口添加获取所有 resource 方法 GetAllAsync

代码语言:txt
复制
public Task<IEnumerable<Resource>> GetAllAsync();

ResourceManager 里面需要用到 Store,先定义接口 IResourceStore

代码语言:txt
复制
using DotNetNB.Security.Core.Models;

namespace DotNetNB.Security.Core.Store
{
    public interface IResourceStore
    {
        public Task CreateAsync(Resource resource);

        public Task CreateAsync(IEnumerable<Resource> resources);

        public Task<IEnumerable<Resource>> GetAllAsync();
        
        public Task<Resource> GetByKeyAsync(string key);

        public Task<IEnumerable<Resource>> GetByKeysAsync(IEnumerable<string> resources);
    }
}

创建 DefaultResourceStore 实现 IResourceStore

代码语言:txt
复制
using DotNetNB.Security.Core.Models;

namespace DotNetNB.Security.Core.Store
{
    public class DefaultResourceStore : IResourceStore
    {
        private readonly List<Resource> _list;

        public DefaultResourceStore()
        {
            _list = new List<Resource>();
        }

        public async Task CreateAsync(Resource resource)
        {
            _list.Add(resource);
        }

        public async Task CreateAsync(IEnumerable<Resource> resources)
        {
            _list.AddRange(resources);
        }

        public async Task<IEnumerable<Resource>> GetAllAsync()
        {
            return _list;
        }

        public async Task<Resource> GetByKeyAsync(string key)
        {
            return _list.SingleOrDefault(r => r.Key == key);
        }

        public async Task<IEnumerable<Resource>> GetByKeysAsync(IEnumerable<string> resources)
        {
            return _list.Where(r => resources.Contains(r.Key));
        }
    }
}

在 ResourceManager 中通过 ResourceStore 创建存储获取 Resource,创建的时候判断是否已经存在 Resource

代码语言:txt
复制
using DotNetNB.Security.Core.Models;
using DotNetNB.Security.Core.Store;

namespace DotNetNB.Security.Core
{
    public class ResourceManager :  IResourceManager
    {
        private readonly IResourceStore _resourceStore;
        public ResourceManager(IResourceStore resourceStore)
        {
            _resourceStore = resourceStore;
        }

        public async Task CreateAsync(Resource resource)
        {
            var origin = await _resourceStore.GetByKeyAsync(resource.Key);
            if (origin != null)
                throw new InvalidOperationException("Duplicated resource key found");

            await _resourceStore.CreateAsync(resource);
        }

        public async Task CreateAsync(IEnumerable<Resource> resources)
        {
            var origins = await _resourceStore.GetByKeysAsync(resources.Select(r => r.Key));
            if (origins.Any())
                throw new InvalidOperationException($"Duplicated resource key found:{string.Concat(origins.Select(o => o.Key), ",")}");

            await _resourceStore.CreateAsync(resources);
        }

        public async Task<IEnumerable<Resource>> GetAllAsync()
        {
            return await _resourceStore.GetAllAsync();
        }

        public async Task<IEnumerable<Resource>> GetByKeysAsync(IEnumerable<string> resources)
        {
            return await _resourceStore.GetByKeysAsync(resources);
        }
    }
}

GitHub源码链接:

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
    • 开发任务
      • 代码实现
        • GitHub源码链接:
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com