PowerDotNet平台化软件架构设计与实现系列(12):HCRM人员管理平台
技术服务于业务,良好的技术设计和实现能够大幅提升业务质量和效率。
PowerDotNet已经形成了自己的开发风格,很多项目已被应用于生产环境,可行性可用性可靠性都得到了生产环境验证。
编程是非常讲究动手实践的科目,我们发明的框架、工具和方法论,如果自己都没有做出有说服力的产品,没有得到充分验证,如何说服别人使用呢?
眼看千遍,嘴说万遍,不如亲自动手实现一遍,咩哈哈。
从本文开始,将会介绍几种像第一篇基础数据平台一样,个人开发过的公共服务中更偏重于业务的公共服务系统,没错,某些业务系统也能成为全局通用的公共服务。
从第2篇到第11篇,更加偏重于公共框架服务、中间件和通用模块,而不是具体业务,这个都是开发业务逻辑程序的前期准备过程,是为了更快更好可扩展可伸缩可运维兼顾灵活性的开发业务系统。
PowerDotNet设计与实现的一个重要目标就是,对于通用和常用模块或功能,解耦并复用,减少重复建设,动动鼠标搞定一切脚手架型的框架搭建。
有了前面那些文章的铺垫,对于业务系统使用公共框架、中间件或服务,基本就是动动鼠标的事情。
我个人接触的广义的CRM,通常包括HCRM(人员或员工管理)、PCRM(个人用户管理)和ECRM(企业用户管理)。
本文只介绍HCRM人员管理平台(侧重于通用权限管理)这一部分,人员管理平台相对基础数据平台业务逻辑更复杂一点,对于PowerDotNet而言只能算是小试牛刀。后续有空再介绍PCRM和ECRM。
我们在开发应用的时候,总需要和不同的人员打交道,比如一线业务、二线支持人员等。根据经验,为他们开发合适的业务系统也是很有挑战的事情,尤其是某些业务(如拉取订单、办公打卡等)某些时间段业务高峰期,设计实现没处理好,很容易遇到性能瓶颈。
经过系统分析抽象和设计,我们发展出了HCRM系统,主要用于人员管理。
在前面介绍PowerDotNet的多篇文章中,我们总是能看到不同系统的管理后台,每个管理后台的菜单几乎都不一样。这些管理后台通用权限的开发,都离不开HCRM的设计与实现。
本文举几个常见功能,说说HCRM的平台建设。
环境准备
1、(必须).Net Framework4.5+
2、(必须)关系型数据库MySQL或SqlServer或PostgreSQL或MariaDB四选一
3、(必须)PowerDotNet数据库管理平台,主要使用DBKey功能
4、(必须)PowerDotNet配置中心Power.ConfigCenter
5、(必须)PowerDotNet注册中心Power.RegistryCenter
6、(必须)PowerDotNet缓存平台Power.Cache
7、(必须)PowerDotNet消息平台Power.Message
8、(必须)PowerDotNet文件平台Power.File(主要包括自定义头像上传、业务单据文件或附件上传等)
9、(必须)PowerDotNet基础数据平台Power.BaseData
一、人员权限
根据经验,权限大概可以抽象为如下三个分类
1、功能权限
功能权限是我们日常生活中最常见最直观理解的一种权限类别,主要解决能做什么的问题,如增加人员、修改资料等。
根据基于角色的权限控制(RBAC),设计实现人员功能权限管理。
有了用户,就需要关联用户角色(也可以通过用户分组对多个用户进行角色关联,用户分组下面介绍)
按照用户分组批量分配角色的情况也很常用,可以节省大量配置时间
再通过角色关联权限,就可以间接得到用户和权限的关系 (角色之间的权限则可以通过页面工具进行批量复制处理)
上面的示例,基本上是最基础简单高效的用户-角色-权限设计,事实上还可以对角色和权限再进行分组抽象,不过大多数业务没有必要,最基础的RBAC就是最强大的武器。
设计权限时,可以权限到菜单,也可以权限到按钮。权限是一种层级关系:
PowerDotNet在设计实现权限和菜单的时候,参考了很多现有设计,很多现成的方案都是菜单资源直接拿来当做权限使用,PowerDotNet则摒弃了这一做法,设计出了更加通用强大的自定义菜单系统。
一个重要原则是,菜单主要负责显示,有样式,有链接,有表现行为,而权限是静态数据,需要和菜单进行匹配关联才能起作用,权限不等于菜单,从而最大限度的复用权限和菜单功能。
实现权限控制到BS页面或者按钮也很简单,充分利用过滤器特性ActionFilterAttribute就行,提示也非常友好。参考下图:
CS结构的则更加简单,通过一个字典方法即可搞定。
2、数据权限
数据权限主要是为了解决能看到哪些(范围)数据的问题,常见的业务场景比如:公司业务部门领导能查看所有下级的业务数据,普通人员只能查看本人的业务单据。
数据权限是对功能权限在纵向的扩展。
3、字段权限
字段权限主要是为了解决能看到哪些(字段)信息的问题,常见的业务场景比如:可以禁止指定用户或角色对某些敏感字段(如账户金额、短信内容等)的访问。
字段权限是对功能权限在横向的扩展。
PowerDotNet目前完美支持数据权限和字段权限控制,PowerDotNet把数据权限和字段权限直接抽象为带有DBKey和SQL语句的功能权限。
数据和字段权限控制主要通过抽象出如下几个和SQL查询有关的字段:
SelectSQL:SQL语句的SELECT部分,支持SELECT *或SELECT 具体字段
TableName:SQL语句的FROM部分,支持数据表、临时表、视图、子查询等
WhereSQL:SQL语句的WHERE部分,支持占位符(通过{参数名}的形式),支持参数化@符号,只要构造好查询条件对象,框架自动构造并解析参数
OrderBySQL:SQL语句的ORDER BY部分,对查询数据结果排序
GroupBySQL:SQL语句的GROUP BY部分
HavingSQL:SQL语句的HAVING部分
PagerSQL:SQL语句的分页部分,分页通常由ORM搞定,这里基本用不到,目前支持{CurrentPage}和{RecordCount}两个动态条件
QuerySQL:完整SQL语句,支持参数化,如果查询结构简单,可以直接写完整SQL语句,不需要动态拼接
PowerDotNet的数据库ORM框架提供通用泛型GetPreparedSQL<T>(DataPurview permission, T qo)方法,内部动态拼接数据权限SQL语句,参数通过泛型方法GetDynamicParams<T>(string sql, T qo)反射构造完成。
通过上述两个框架方法,可以控制任意的数据权限和字段权限,绝大多数场景下的查询问题都可迎刃而解。
相比一些其他的数据和字段权限解决方案,PowerDotNet的权限控制不需要构造复杂的条件表达式和数据匹配关系,SQL完全由权限开发者掌握,配合DBKey万能SQL查询接口自动完成数据和字段权限功能。
二、人员分组
人员分组是为了满足可扩展性、可伸缩性以及灵活性而特意设计的。
组织机构的设计天生就是用来对人员进行分组的。
对于一般公司而言,基本的组织机构就是公司部门,每次新增一个员工,自动就会进入公司部门分组。
但是常见的公司部门组织机构还远远不够,现实的人员分组情况远远比一般的公司部门型的组织结构更复杂。
前面我们提到,“可以对角色和权限再进行分组抽象”,HCRM经过权衡后没有对角色和权限做出这种复杂设计。
但是人员关系必须要分组才能更好解决问题。
为了更好地管理人员,对人员进行分组归类,PowerDotNet继续抽象,设计出HCRM通用的人员分组。
人员分组之间也有关系,常见的关系结构包括:
1、一维结构:人员分组之间是平等的,没有包含与被包含之分。
2、树形结构:每个人员分组可以有一个或零个父级人员分组。
3、多父结构:每个人员分组可以有多个或一个或零个父级人员分组,但不能形成循环依赖。
HCRM的人员分组原来设计是有经典的树状结构的上下级关系的,但是根据实际使用经验,树状层级关系在人员分组里基本属于过度设计,所以最新版本已经去掉了这个功能。
使用HCRM的人员分组功能,必须遵循一定的规范。
一个分组可以有多个用户,一个人员可以加入多个分组。
对于常见的人员层级关系,比如公司部门有部门领导,仓库有仓库负责人,门店有店长......这种人员层级关系也能通过人员分组的一维结构设计来解决。
人员分组支持设置直接领导,查询时稍加转换,自动支持了人员层级关系。
人员分组管理主要涉及三张表,即人员和分组关系表(emp_refer_group)、人员分组表(emp_group)、分组数据源表(group_data_source)。
分组数据源表(group_data_source)比较特殊,设计它主要是为了拿到对接的业务组织机构ID和名称(biz_dept_id,如公司部门Id、仓库Id、转运中心Id、前置仓Id、配送站点Id等等),因为PowerDotNet的服务治理框架和数据同步平台的存在,这个表通常情况下几乎可以不用。
因为人员分组表(emp_group)设计的好,emp_group的biz_data_source字段支持text、xml、json、或者直接服务名称、数据表名称。绝大多数的数据源场景都覆盖到了,非常有利于动态扩展。
通常对接业务方通过服务治理平台注册下数据源接口就可以了,也可以通过数据同步平台同步业务数据至HCRM分组数据源表(group_data_source),这两种模式非常有利于扩展各种数据源。
PowerDotNet建议直接通过服务治理平台,按照约定好的数据源契约,业务方提供数据源接口,HCRM不写一行代码就在配置中心配置下服务接口名称,服务治理框架自动搞定一切,对于各种新业务或者扩展业务做到完美兼容支持。
PowerDotNet的HCRM系统目前默认完美支持的组织机构类型包括公司部门、仓库、配送中心、配送站点、自提点、网点、转运中心、实体门店(如酒店等)、前置仓、供应商等,只要在管理后台点点按钮就可以支持更多这种可扩展的人员分组关系。
人员分组类型也支持动态“无限”灵活配置。
目前为止,HCRM这一套人员分组设计都运行良好。
三、人员登录
简简单单一个登录功能,需要考虑并涉及到很多方面,包括登录用户名设计(通常支持用户名、工号、邮箱和手机)、cookie、session、token、http和https、LDAP、单点登录、“记住我”功能设计、登录试错次数、登录信息有效期、登录信息是否脱敏、强制退出(踢出)、验证码、安全问答、密码强度、重置密码、语音登录、二维码扫码登录、OAuth或OAuth2、登录安全日志等。
登录需要注意的最大问题是信息安全,鲁迅先生说“不惮以最坏的恶意来推测中国人”,对于信息安全,哪怕是内部人员管理系统,也要做最保守的安全防御编程。
别看登录功能基础且简单,设计不好,三天两头出问题,别问我怎么知道的,有些公司开发的系统之让人无语程度绝对超乎你的想象。
HCRM在设计登录功能的时候参考了很多公司和开源项目的现有实现,并提取出精华部分加以利用,已经在生产环境得到了验证。
HCRM这一套安全防御实现对后续开发PCRM和ECRM也有极其重要的参考价值,有空后续文章再介绍。
HCRM对外公开接口,用于用户登录:
每个管理后台基于Asp.Net的安全框架实现Form认证登录功能。
验证码长度可配置,可以根据实际页面效果调整验证码长度,否则验证码图片容易失真。
除了用户名、密码外,还可以通过手机、邮箱、工号等登录,登录功能可以扩展,支持OAuth等方式的授权登录。
支持验证码的动态生成和销毁,是否需要验证码以及验证码长度可通过配置中心动态配置来控制。
支持公共服务统一集成平台的基于Redis加Token的登录方式。
早期通过JWT实现用户登录认证基本逻辑,根据经验,绝大多数情况下JwtToken也就是当一个加密的cookie来用。
后续随着业务变化需要,JWT被改造为直接通过Redis+Token,实现通用的登录、授权、鉴权、安全退出等逻辑。
四、人事管理
人事管理完全可以单独部署成独立应用,但是为了介绍方便,还是在HCRM里一起贴图说明下。
个人工作过的公司基本都有一整套完善的HCRM人员管理系统,常见模块包括人事基础、员工档案管理、招聘职位管理、考勤管理、薪资管理、假期管理、在线申请单据管理、报销凭证管理、报表管理、流程管理、组织架构管理、关联账号管理、员工职级管理、投票管理、会议管理、合同管理、常用资料管理等等。有些还和OA整合在一起,极大地提升无纸化办公效率。
PowerDotNet实现的HCRM系统自动集成了人事基础和常用人事管理,中小公司基本够用,简单截图看一下:
1、人事基础
2、人事管理
人事管理中,员工工资管理模块,对保密性、可靠性和权限控制有更高的要求,对工资的查看和操作都有详细审计日志(日志也要脱敏),保证数据安全,HCRM已经完美支持员工工资和员工调薪管理。
当然本文重点主要介绍最常见最通用的RBAC和登录,这是各种互联系统中最最基础的模块之一。
五、总结
HCRM人员管理平台实现了常见的丰富的可扩展的人员管理功能,主要包括人员管理、通用权限管理、人员分组管理、登录管理、人事管理等核心模块。
目前PowerDotNet的通用权限管理已经自动集成对接所有PowerDotNet公共服务系统,仅需要很少的模板代码,就可以将权限控制到菜单、按钮和文件。数据和字段权限功能也只需要很少的业务代码(简单的则一行代码也不要接入方写,只要HCRM权限配置好SQL就行)即可自动集成。
现在新的应用想对接PowerDotNet的通用权限,仅需在管理后台点点按钮,后端埋点权限模板代码,不论BS(支持VUE和React等SPA应用)还是CS结构的应用程序,整个权限设置过程不超过5分钟就对接完成了,大大降低了权限控制门槛。
作者:Jeff Wong
出处:http://jeffwongishandsome.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。