前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[NewLife.XCode]角色权限

[NewLife.XCode]角色权限

作者头像
大石头
发布2019-07-02 17:30:28
2.1K0
发布2019-07-02 17:30:28
举报
文章被收录于专栏:智能大石头智能大石头

NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。

整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含多年开发经验于其中,代表作有百亿级大数据实时计算项目。

开源地址:https://github.com/NewLifeX/X

前面讲解了XCode的各种用法,这一章我们来讲讲内置的Membership,同时也是XCode的第一标准示例!

设计背景

现代管理信息系统绝大部分采用BS架构,无一例外需要用户角色权限的支持!

结合团队诸多兄弟姐妹的经验,设计了一个大小适中的用户权限系统Membership,目标是满足80%的使用场景,并具备一定的扩展性。

Membership刚开始就采用了角色授权体系,每个用户只有一种角色,角色拥有菜单资源权限集。

随着Membership实用性日益增加,2015年初正式合并进入XCode,作为一个模块存在。

2016年第二代魔方NewLife.Cube采用ASP.Net MVC5重构,让Membership的荣誉达到了鼎峰!

在MVC中,每个Controller就是一个菜单资源,其下的Search/Detail/Insert/Update/Delete等Action作为角色在该菜单资源下的权限子项,保存在角色属性数据中。

2018年为了增强魔方功能,在某些场景下支持单用户多角色,且兼容已有系统,用户表增加RoleIDs字段,保存扩展角色,原来的RoleID作为主角色。

管理提供者

管理提供者接口 IManageProvider ,提供了Membership基本操作实现。

  1. 当前登录用户 GetCurrent、SetCurrent,静态访问 ManageProvider.User
  2. 查找用户 FindByID、FindByName
  3. 注册登录注销 Register、Login、Logout
  4. 当前用户主机(访问者IP)ManageProvider.UserHost
  5. IManageProvider 默认由XCode.Membership中的UserX/Role/Menu支持,如若用户使用自己的用户权限表,可重新实现该接口

用户权限

用户 UserX

用户数据模型:

代码语言:javascript
复制
  <Table Name="User" Description="用户" RenderGenEntity="true">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="Name" DataType="String" Master="True" Nullable="False" Description="名称。登录用户名" />
      <Column Name="Password" DataType="String" Description="密码" />
      <Column Name="DisplayName" DataType="String" Description="昵称" />
      <Column Name="Sex" DataType="Int32" Description="性别。未知、男、女" Type="SexKinds" />
      <Column Name="Mail" DataType="String" Description="邮件" />
      <Column Name="Mobile" DataType="String" Description="手机" />
      <Column Name="Code" DataType="String" Description="代码。身份证、员工编号等" />
      <Column Name="Avatar" DataType="String" Length="200" Description="头像" />
      <Column Name="RoleID" DataType="Int32" Description="角色。主要角色" />
      <Column Name="RoleIDs" DataType="String" Length="200" Description="角色组。次要角色集合" />
      <Column Name="DepartmentID" DataType="Int32" Description="部门。组织机构" />
      <Column Name="Online" DataType="Boolean" Description="在线" />
      <Column Name="Enable" DataType="Boolean" Description="启用" />
      <Column Name="Logins" DataType="Int32" Description="登录次数" />
      <Column Name="LastLogin" DataType="DateTime" Description="最后登录" />
      <Column Name="LastLoginIP" DataType="String" Description="最后登录IP" />
      <Column Name="RegisterTime" DataType="DateTime" Description="注册时间" />
      <Column Name="RegisterIP" DataType="String" Description="注册IP" />
      <Column Name="Ex1" DataType="Int32" Description="扩展1" />
      <Column Name="Ex2" DataType="Int32" Description="扩展2" />
      <Column Name="Ex3" DataType="Double" Description="扩展3" />
      <Column Name="Ex4" DataType="String" Description="扩展4" />
      <Column Name="Ex5" DataType="String" Description="扩展5" />
      <Column Name="Ex6" DataType="String" Description="扩展6" />
      <Column Name="UpdateUser" DataType="String" Description="更新用户" />
      <Column Name="UpdateUserID" DataType="Int32" Description="更新用户" />
      <Column Name="UpdateIP" DataType="String" Description="更新地址" />
      <Column Name="UpdateTime" DataType="DateTime" Nullable="False" Description="更新时间" />
      <Column Name="Remark" DataType="String" Length="200" Description="备注" />
    </Columns>
    <Indexes>
      <Index Columns="Name" Unique="True" />
      <Index Columns="RoleID" />
      <Index Columns="UpdateTime" />
    </Indexes>
  </Table>

常用字段有ID、用户名和密码,登录注册相关信息;

角色RoleID、RoleIDs用于实现权限集控制;

部分场景需要邮箱Mail、手机Mobile或者工号Code登录;

如果仍然不能满足要求,可以考虑使用Ex1~Ex6等扩展字段。

常用功能点:

  1. 初始化时,如果数据表为空,自动插入admin/admin用户账号,角色是“管理员”
  2. 支持注册登录,使用MD5保存密码
  3. 支持编号查询FindByID和名称查询FindByName,分别采用了对象缓存和对象从键,轻松实现百万级账号快速查询
  4. 支持IIdentity接口

角色 Role

角色数据模型:

代码语言:javascript
复制
  <Table Name="Role" Description="角色" RenderGenEntity="true">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="Name" DataType="String" Master="True" Nullable="False" Description="名称" />
      <Column Name="Enable" DataType="Boolean" Description="启用" />
      <Column Name="IsSystem" DataType="Boolean" Description="系统。用于业务系统开发使用,不受数据权限约束,禁止修改名称或删除" />
      <Column Name="Permission" DataType="String" Length="500" Description="权限。对不同资源的权限,逗号分隔,每个资源的权限子项竖线分隔" />
      <Column Name="Ex1" DataType="Int32" Description="扩展1" />
      <Column Name="Ex2" DataType="Int32" Description="扩展2" />
      <Column Name="Ex3" DataType="Double" Description="扩展3" />
      <Column Name="Ex4" DataType="String" Description="扩展4" />
      <Column Name="Ex5" DataType="String" Description="扩展5" />
      <Column Name="Ex6" DataType="String" Description="扩展6" />
      <Column Name="CreateUser" DataType="String" Description="创建用户" />
      <Column Name="CreateUserID" DataType="Int32" Description="创建用户" />
      <Column Name="CreateIP" DataType="String" Description="创建地址" />
      <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" />
      <Column Name="UpdateUser" DataType="String" Description="更新用户" />
      <Column Name="UpdateUserID" DataType="Int32" Description="更新用户" />
      <Column Name="UpdateIP" DataType="String" Description="更新地址" />
      <Column Name="UpdateTime" DataType="DateTime" Nullable="False" Description="更新时间" />
      <Column Name="Remark" DataType="String" Length="200" Description="备注" />
    </Columns>
    <Indexes>
      <Index Columns="Name" Unique="True" />
    </Indexes>
  </Table>

角色表比较简单主要是名称和启用,以及保存菜单权限数据的Permission

角色支持的操作权限:

代码语言:javascript
复制
    /// <summary>操作权限</summary>
    [Flags]
    [Description("操作权限")]
    public enum PermissionFlags
    {
        /// <summary>无权限</summary>
        [Description("无权限")]
        None = 0,

        /// <summary>查看权限</summary>
        [Description("查看")]
        Detail = 1,

        /// <summary>添加权限</summary>
        [Description("添加")]
        Insert = 2,

        /// <summary>修改权限</summary>
        [Description("修改")]
        Update = 4,

        /// <summary>删除权限</summary>
        [Description("删除")]
        Delete = 8,

        /// <summary>所有权限</summary>
        [Description("所有")]
        All = 0xFF,
    }

主要功能点:

  1. 数据表为空时初始化4个基本角色:管理员、高级用户、普通用户、游客
  2. 启动时角色权限校验,清理角色中无效的权限项(可能菜单已删除),以及授权管理员访问所有角色都无权访问的新菜单
  3. 支持编号查询FindByID和名称查询FindByID,采用实体缓存,目标系统不会超过1000个角色
  4. 支持权限判断与设置 Has/Get/Set/Reset 等
  5. 重载实体类 Delete/Save/Update/OnLoad/OnPropertyChanged,加载实体对象时展开权限,保存时合并

菜单 Menu

菜单数据模型:

代码语言:javascript
复制
  <Table Name="Menu" Description="菜单" BaseType="EntityTree" RenderGenEntity="true">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="Name" DataType="String" Master="True" Nullable="False" Description="名称" />
      <Column Name="DisplayName" DataType="String" Description="显示名" />
      <Column Name="FullName" DataType="String" Length="200" Description="全名" />
      <Column Name="ParentID" DataType="Int32" Description="父编号" />
      <Column Name="Url" DataType="String" Length="200" Description="链接" />
      <Column Name="Sort" DataType="Int32" Description="排序" />
      <Column Name="Icon" DataType="String" Description="图标" />
      <Column Name="Visible" DataType="Boolean" Description="可见" />
      <Column Name="Necessary" DataType="Boolean" Description="必要。必要的菜单,必须至少有角色拥有这些权限,如果没有则自动授权给系统角色" />
      <Column Name="Permission" DataType="String" Length="200" Description="权限子项。逗号分隔,每个权限子项名值竖线分隔" />
      <Column Name="Ex1" DataType="Int32" Description="扩展1" />
      <Column Name="Ex2" DataType="Int32" Description="扩展2" />
      <Column Name="Ex3" DataType="Double" Description="扩展3" />
      <Column Name="Ex4" DataType="String" Description="扩展4" />
      <Column Name="Ex5" DataType="String" Description="扩展5" />
      <Column Name="Ex6" DataType="String" Description="扩展6" />
      <Column Name="CreateUser" DataType="String" Description="创建用户" />
      <Column Name="CreateUserID" DataType="Int32" Description="创建用户" />
      <Column Name="CreateIP" DataType="String" Description="创建地址" />
      <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" />
      <Column Name="UpdateUser" DataType="String" Description="更新用户" />
      <Column Name="UpdateUserID" DataType="Int32" Description="更新用户" />
      <Column Name="UpdateIP" DataType="String" Description="更新地址" />
      <Column Name="UpdateTime" DataType="DateTime" Nullable="False" Description="更新时间" />
      <Column Name="Remark" DataType="String" Length="200" Description="备注" />
    </Columns>
    <Indexes>
      <Index Columns="Name" />
      <Index Columns="ParentID,Name" Unique="True" />
    </Indexes>
  </Table>

菜单实体类采用树形实体基类 EntityTree ,通过 ParentID 实现上下级关联,同级 ParentID+Name 唯一

主要功能点:

  1. 支持自动扫描Controller作为菜单,因此魔方只需要增加Controller,即可在菜单表看到新页面
  2. 实体树适用于1000行以内树形数据表,一次性加载数据到内存,在内存中根据ParentID构造实体对象树,最常用树形是Parent/Childs

日志统计

日志 Log

数据模型:

代码语言:javascript
复制
  <Table Name="Log" Description="日志" ConnName="Log" RenderGenEntity="true">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="Category" DataType="String" Description="类别" />
      <Column Name="Action" DataType="String" Description="操作" />
      <Column Name="LinkID" DataType="Int32" Description="链接" />
      <Column Name="UserName" DataType="String" Description="用户名" />
      <Column Name="Ex1" DataType="Int32" Description="扩展1" />
      <Column Name="Ex2" DataType="Int32" Description="扩展2" />
      <Column Name="Ex3" DataType="Double" Description="扩展3" />
      <Column Name="Ex4" DataType="String" Description="扩展4" />
      <Column Name="Ex5" DataType="String" Description="扩展5" />
      <Column Name="Ex6" DataType="String" Description="扩展6" />
      <Column Name="CreateUser" DataType="String" Description="创建用户" />
      <Column Name="CreateUserID" DataType="Int32" Description="用户编号" />
      <Column Name="CreateIP" DataType="String" Description="IP地址" />
      <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="时间" />
      <Column Name="Remark" DataType="String" Length="500" Description="详细信息" />
    </Columns>
    <Indexes>
      <Index Columns="Category" />
      <Index Columns="CreateUserID" />
      <Index Columns="CreateTime" />
    </Indexes>
  </Table>

日志表记录分类、操作和日志内容。

主要功能点:

  1. 日志提供者LogProvider,提供了唯一核心方法 WriteLog,默认实现就是写该日志表。可从对象容器取得日志提供者 ObjectContainer.Resolve<LogProvider>()
  2. 从IManageProvider接口获取当前登录用户以及远程访问IP写入日志相应字段

在线 UserOnline

数据模型:

代码语言:javascript
复制
  <Table Name="UserOnline" Description="用户在线" ConnName="Log">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="UserID" DataType="Int32" Description="用户" />
      <Column Name="Name" DataType="String" Master="True" Description="名称" />
      <Column Name="SessionID" DataType="String" Description="会话。Web的SessionID或Server的会话编号" />
      <Column Name="Times" DataType="Int32" Description="次数" />
      <Column Name="Page" DataType="String" Description="页面" />
      <Column Name="Status" DataType="String" Length="200" Description="状态" />
      <Column Name="OnlineTime" DataType="Int32" Description="在线时间。本次在线总时间,秒" />
      <Column Name="CreateIP" DataType="String" Description="创建地址" />
      <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" />
      <Column Name="UpdateTime" DataType="DateTime" Nullable="False" Description="修改时间" />
    </Columns>
    <Indexes>
      <Index Columns="UserID" />
      <Index Columns="SessionID" />
      <Index Columns="CreateTime" />
    </Indexes>
  </Table>

借助用户行为模块 UserBehaviorModule , 维护用户在线记录,持久化在 UserOnline 表

访问统计 VisitStat

代码语言:javascript
复制
  <Table Name="VisitStat" Description="访问统计" ConnName="Log">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="Level" DataType="Int32" Description="层级" Type="XCode.Statistics.StatLevels" />
      <Column Name="Time" DataType="DateTime" Description="时间" />
      <Column Name="Page" DataType="String" Nullable="False" Description="页面" />
      <Column Name="Title" DataType="String" Master="True" Description="标题" />
      <Column Name="Times" DataType="Int32" Description="次数" />
      <Column Name="Users" DataType="Int32" Description="用户" />
      <Column Name="IPs" DataType="Int32" Description="IP" />
      <Column Name="Error" DataType="Int32" Description="错误" />
      <Column Name="Cost" DataType="Int32" Description="耗时。毫秒" />
      <Column Name="MaxCost" DataType="Int32" Description="最大耗时。毫秒" />
      <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" />
      <Column Name="UpdateTime" DataType="DateTime" Nullable="False" Description="更新时间" />
      <Column Name="Remark" DataType="String" Length="5000" Description="详细信息" />
    </Columns>
    <Indexes>
      <Index Columns="Page,Level,Time" Unique="True" />
      <Index Columns="Level,Time" />
    </Indexes>
  </Table>

借助用户行为模块 UserBehaviorModule , 维护用户访问记录,写入日志表,并写入访问统计表。

主要功能要点:

  1. 记录页面访问统计,简单支持IP数和用户数
  2. 支持年月日三级统计,作为XCode日期统计表的标准示例

其它

部门 Department

数据模型:

代码语言:javascript
复制
  <Table Name="Department" Description="部门。组织机构,多级树状结构" BaseType="EntityTree" RenderGenEntity="true">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="Code" DataType="String" Description="代码" />
      <Column Name="Name" DataType="String" Master="True" Nullable="False" Description="名称" />
      <Column Name="FullName" DataType="String" Length="200" Description="全名" />
      <Column Name="ParentID" DataType="Int32" Description="父级" />
      <Column Name="Level" DataType="Int32" Description="层级。树状结构的层级" />
      <Column Name="Sort" DataType="Int32" Description="排序。同级内排序" />
      <Column Name="Enable" DataType="Boolean" Description="启用" />
      <Column Name="Visible" DataType="Boolean" Description="可见" />
      <Column Name="Ex1" DataType="Int32" Description="扩展1" />
      <Column Name="Ex2" DataType="Int32" Description="扩展2" />
      <Column Name="Ex3" DataType="Double" Description="扩展3" />
      <Column Name="Ex4" DataType="String" Description="扩展4" />
      <Column Name="Ex5" DataType="String" Description="扩展5" />
      <Column Name="Ex6" DataType="String" Description="扩展6" />
      <Column Name="CreateUser" DataType="String" Description="创建用户" />
      <Column Name="CreateUserID" DataType="Int32" Description="创建用户" />
      <Column Name="CreateIP" DataType="String" Description="创建地址" />
      <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" />
      <Column Name="UpdateUser" DataType="String" Description="更新用户" />
      <Column Name="UpdateUserID" DataType="Int32" Description="更新用户" />
      <Column Name="UpdateIP" DataType="String" Description="更新地址" />
      <Column Name="UpdateTime" DataType="DateTime" Nullable="False" Description="更新时间" />
      <Column Name="Remark" DataType="String" Length="200" Description="备注" />
    </Columns>
    <Indexes>
      <Index Columns="Name" />
      <Index Columns="ParentID,Name" Unique="True" />
      <Index Columns="Code" />
      <Index Columns="UpdateTime" />
    </Indexes>
  </Table>

字典参数 Parameter

数据模型:

代码语言:javascript
复制
  <Table Name="Parameter" Description="字典参数">
    <Columns>
      <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
      <Column Name="Category" DataType="String" Description="类别" />
      <Column Name="Name" DataType="String" Master="True" Description="名称" />
      <Column Name="Value" DataType="String" Length="200" Description="数值" />
      <Column Name="LongValue" DataType="String" Length="2000" Description="长数值" />
      <Column Name="Kind" DataType="Int32" Description="种类。0普通,21列表,22名值" Type="XCode.Membership.ParameterKinds" />
      <Column Name="Enable" DataType="Boolean" Description="启用" />
      <Column Name="Ex1" DataType="Int32" Description="扩展1" />
      <Column Name="Ex2" DataType="Int32" Description="扩展2" />
      <Column Name="Ex3" DataType="Double" Description="扩展3" />
      <Column Name="Ex4" DataType="String" Description="扩展4" />
      <Column Name="Ex5" DataType="String" Description="扩展5" />
      <Column Name="Ex6" DataType="String" Description="扩展6" />
      <Column Name="CreateUser" DataType="String" Description="创建用户" />
      <Column Name="CreateUserID" DataType="Int32" Description="创建用户" />
      <Column Name="CreateIP" DataType="String" Description="创建地址" />
      <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" />
      <Column Name="UpdateUser" DataType="String" Description="更新用户" />
      <Column Name="UpdateUserID" DataType="Int32" Description="更新用户" />
      <Column Name="UpdateIP" DataType="String" Description="更新地址" />
      <Column Name="UpdateTime" DataType="DateTime" Nullable="False" Description="更新时间" />
      <Column Name="Remark" DataType="String" Length="200" Description="备注" />
    </Columns>
    <Indexes>
      <Index Columns="Category,Name" Unique="True" />
      <Index Columns="Name" />
      <Index Columns="UpdateTime" />
    </Indexes>
  </Table>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-06-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设计背景
  • 管理提供者
  • 用户权限
    • 用户 UserX
      • 角色 Role
        • 菜单 Menu
        • 日志统计
          • 日志 Log
            • 在线 UserOnline
              • 访问统计 VisitStat
              • 其它
                • 部门 Department
                  • 字典参数 Parameter
                  相关产品与服务
                  消息队列 TDMQ
                  消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档