红皮书-1.0用户权限技术新一代云ERP解决方案2目录一.前言..31.1.背景..3二.功能概要.42.1.角色管理.42.1.1.基本说明..42.1.2.信任公司..52.1.3.公司管理员角色..52.1.4.分配公司..62.1.5.设置角色中的用户.72.2.权限分配.82.3.用户管理.82.4.资源权限控制..102.5.权限资源配置..102.6.功能权限查询..11三.插件开发及升级开发.113.1.开发要求..113.2.插件开发..113.2.1.树形(如下权限分配展现为树形).113.2.2.表格形(如下权限分配展现为表格形).123.2.3.数据库、多语言翻译要求..12四.特性说明..15五.附录.165.1.引用的JAVADOC文档.165.2.引用的代码范例..18新一代云ERP解决方案3一.前言U8cloud用户权限采用RBAC模型(Role-BasedAccessControl,基于角色的访问控制),引入角色,以角色为桥梁把用户和权限连接起来,用户只需关注其在组织结构中担当的角色,而角色所拥有的权限由角色本身决定,这样用户通过担当角色而拥有相应权限。1.1.背景传统的用户权限没有形成统一的体系,功能权限和数据权限各自为政,越来越难以满足用户的各种复杂需求,特别是不能满足权限集中控制的应用模式,并且导致系统运行效率越来越低。而基于角色的访问控制(RBAC)模型目前已经非常成熟和流行,并且非常适合我们这种ERP应用,所以有必要借鉴之,整合功能权限和数据权限,进行统一管理,以实现权限的各种应用模式,提高系统效率。新一代云ERP解决方案4二.功能概要2.1.角色管理2.1.1.基本说明1.角色为权限的一个集合,具体表示组织中的一个职责、或者一个工作、或者一个任务等等。2.角色管理维护角色的基本信息(角色编码和名称等),并且设置角色中的用户。上级公司可以管理本公司和所有下级公司角色。3.资源类型:有公司类型、主体帐簿类型和复合类型。角色的资源类型不同,则能够分配的功能权限也不同;对于主体帐簿类型的角色,只能分配总帐模块下节点的功能权限;而公司类型的角色,能够分配除总帐模块下节点外所有节点的功能权限;复合类型的角色能够分配所有的功能权限。图1角色管理信任公司新一代云ERP解决方案52.1.2.信任公司为角色设置信任公司(如上图),为了达到角色让其他公司用户兼职目的,并且角色只在创建公司有效。例1:C1公司的R1角色信任C2公司,则C2公司的用户可以委派R1角色(相当于此用户在C1公司兼职R1角色,但在C2公司不担当此角色),那么C2公司用户能登录公司C1,并且具有角色R1的权限。图2角色信任公司2.1.3.公司管理员角色1.公司管理员角色负责用户权限管理,而其他角色不能进行用户权限管理。2.担当此角色的用户可以管理本公司和下级公司的用户权限。3.公司用户由上级公司的管理员委派此角色。4.集团的管理员,在进行U8C用户同步时,会自动分配公司管理员角色C1公司R1角色C2公司信任兼职新一代云ERP解决方案62.1.4.分配公司图3分配公司1.为角色分配公司(如上图),相当于每个分配公司也产生了此角色(表示此角色除了属于创建公司外,也属于这些分配公司),并且在创建公司和各分配公司可以具有相同特性和各自不同的特性(参考角色的公共权限和私有权限)。2.例2:C1公司的R1角色分配C2公司,则如果C2公司的用户委派了R1角色(相当于此用户在C2公司担当R1角色,但在C1公司不担当此角色),那么C2公司用户在公司C2具有角色R1的权限。角色的信任和分配的区别:信任不改变角色的作用域,如在例1中,R1角色只在C1公司有效;而分配则扩大了角色的作用域,如在例2中,R1角色在C2公司也有效。C1公司C2公司R1角色分配公司用户新一代云ERP解决方案72.1.5.设置角色中的用户图4角色中设置用户1.角色可以委派给本公司用户,分配到其它公司的角色也可以委派给上级公司用户。例3(和例1、例2区别):C1公司的R1角色分配C2公司,则如果C1公司的用户委派了C2公司的R1角色(相当于此用户在C2公司担当R1角色,当然此用户还可以委派C1公司的R1角色),那么C1公司用户在公司C2具有角色R1的权限。2.配到其它公司的角色也可以委派给那个公司的用户,如例2。在界面上表现为:当为本公司创建的角色设置用户的时候,参照到的为本公司所有的用户;将角色分配给下级公司后,为下级公司的该角色设置用户时参照到的为角色创建公司的所有用户以及此下级公司的用户。C1公司C2公司分配R角色R1角色兼职担当用户新一代云ERP解决方案82.2.权限分配图5权限分配1.权限:对数据进行访问的许可。2.权限分配统一管理,包括功能权限和各种数据权限,为角色分配权限;上级公司可以管理本公司和所有下级公司角色权限。3.采用插件技术定制需要分配的各种权限。权限的业务扩展由插件决定,比如客商权限具体什么业务含义、是否上级控制等。插件主要实现右侧的界面展现,如上图提示,具体实现参考后面的“插件开发及升级开发”。4.角色的公共权限和私有权限:角色的公共权限,表示角色在创建公司和各分配公司都拥有这部分权限;角色的私有权限,表示角色在各公司所拥有的单独权限;而角色在公司具有的权限由角色的公共权限和在此公司的私有权限组成。对于功能权限,分配总账节点权限时,也可以分配公共权限,则这部分权限能在所有主体账簿下使用,并且也能在具体的主体账簿下分配私有权限。2.3.用户管理1.用户指能登录U8cloud系统的用户,是登录账号。用户管理主要维护用户基本信息(编码、名称、口令等),口令策略(认证方式、口令有效期)、用户对应的业务员、角色的委派(用户能够担当的本公司角色和其它公司角色)。2.上级公司可以管理本公司和所有下级公司用户。公共权限插件开发新一代云ERP解决方案9图6用户管理3.用户可以委派本公司创建的角色(见下图),本公司创建的角色包括分配了公司的角色和没有分配公司的角色。可以参考例3。图7用户委派角色用户还可以委派信任本公司的角色(见上图)。可以参考例1。分配了公司的角色未分配公司的角色信任当前公司的其他公司角色新一代云ERP解决方案102.4.资源权限控制1.控制具体公司是否启用权限或者控制具体主体账簿是否启用权限。比如可以控制部分公司启用按钮权限,控制部分主体账簿启用会计科目权限。2.上级公司可以管理本公司和所有下级公司的权限启用。3.在公司或者主体账簿启用权限控制的前提下,还可以控制具体角色是否启用权限,这在角色管理中完成。图8资源权限控制2.5.权限资源配置功能权限最大集控制:在进行权限分配时限制用户能够分配的功能权限,不能超过用户拥有的功能权限。新一代云ERP解决方案112.6.功能权限查询1.查询用户的功能权限、角色的功能权限、功能权限的用户清单、功能权限的角色清单。2.使用查询引擎实现,可以根据业务需求增加或修改查询功能。三.插件开发及升级开发3.1.开发要求U8cloud权限模型采用集中控制模式,已经预制了各种默认插件,比如功能权限插件、会计科目权限插件;如果要增加新的权限资源(比如地区分类),则要开发新的权限插件,最多需要执行2步(具体参考后面的“插件开发”):1.实现权限插件类。2.生成权限表和注册权限脚本。3.2.插件开发3.2.1.树形(如下权限分配展现为树形)1.如果权限分配展现为树形,则插件类继承nc.ui.uap.rbac.editor.tree.DefaultTreeResBusiService。树形新一代云ERP解决方案122.可以参考“收支项目”插件的nc.ui.uap.rbac.service.CostsubjTreeEditorController。3.主要方法介绍:1)booleansetResourceContext(ResourceContextcontext):设置资源的环境变量,建议此方法设置需要返回的需要进行权限分配的数据(由于在此可以比较新和旧的context,判断是否需要查询数据。(详细参考nc.ui.uap.rbac.editor.IResPowerService)。2)getSaveField():要保存的字段名,比如要保存收支项目的主键pk_costsubj。(参考nc.ui.uap.rbac.editor.AbstractResBusiService)。要配合nc.ui.uap.rbac.editor.IResPowerService中的方法getAttributeValue(Objectobj,StringfieldName)而获得属性值。nc.ui.uap.rbac.editor.tree.ITreeEditorController的getTreeNodeProvider用于返回构建树的提供器,具体参看nc.ui.uap.rbac.comp.ItreeNodeProvider;而方法getTreeSelectionMode用于返回树的选择策略,nc.ui.uap.rbac.comp.selmode包提供了很多默认的选择策略,可以直接使用。3.2.2.表格形(如下权限分配展现为表格形)1.如果权限分配展现为表格形,则插件类继承nc.ui.uap.rbac.editor.AbstractResBusiService,再实现接口nc.ui.uap.rbac.editor.table.ITableResBusiService。2.参考“开户银行”插件的nc.ui.uap.rbac.service.AccBankTableService。3.主要方法介绍(参考树形中的方法介绍):a)其中的setResourceContext转化为isNeedReloadData和queryAllResDataByContext处理,分别表示是否需要重新刷新数据和查询数据。b)nc.ui.uap.rbac.editor.table.ITableResBusiService中的showFields和showFieldNames分别表示表格中的显示字段和显示字段名称。3.2.3.数据库、多语言翻译要求(1)生成对应权限表权限表名最好采用规范形式:XX_power_????,XX表示产品组缩写,????表示具体的资表格形新一代云ERP解决方案13源,要符合数据库表的设计规范。权限表的各字段采用统一的内容如下,不要修改字段名和字段size(蓝色表示需要开发修改):createtableXX_power_????(pk_powerCHAR(20)notnull,pk_roleCHAR(20)notnull,resource_data_idVARCHAR(100)notnull,orgtypecodeSMALLINTnotnull,pk_orgVARCHAR(20),iscommon_powerCHAR(1),pk_corpCHAR(4)notnull,tschar(19)nulldefaultconvert(char(19),getdate(),20),drsmallintdefault0,constraintPK_XX_power_????primarykey(pk_power))(2)准备资源权限脚本例如树形“收支项目”的注册为:insertintosm_powerresource(pk_powerresource,resource_id,resource_name,power_tablename,power_editor_class,editor_serviceclass,isorgcontrol,para_control_type,ispowermaxcontrol,ts,dr)values('POWEAA00000000000035',35,'收支项目','sm_power_costsubj','nc.ui.uap.rbac.editor.tree.TreeResourceEditor','nc.ui.uap.rbac.service.CostsubjTreeEditorController','N',1,null,'2018-01-1709:40:39',0)分别表示主键、资源标识(一定不能和其他产品组重复)、资源名称、前面定义的权限表名XX_power_????、树的编辑器(如果有特殊展现,需要注册其子类)、前面开发的权限插件类。例如表格形“开户银行”的注册为:insertintosm_powerresource(pk_powerresource,resource_id,resource_name,power_tablename,power_editor_class新一代云ERP解决方案14,editor_serviceclass,isorgcontrol,para_control_type,ispowermaxcontrol,ischeck_settlecorp,ischeck_corp,ts,dr)values('POWEAA00000000000036',36,'开户银行','sm_power_accbank','nc.ui.uap.rbac.editor.table.TableResourceEditor','nc.ui.uap.rbac.service.AccBankTableService','N',1,null,null,null,'2018-01-1709:40:39',0)和树形注册的不同之处在于表的编辑器为nc.ui.uap.rbac.editor.table.TableResourceEditor,如果有特殊展现,需要注册其子类。(3)权限资源的多语言为了进行多语言翻译,需要在多语言目录101611的文件power_resource.properties添加资源名称的翻译,规则为“RESOURCE-资源标识”(资源标识为上面权限脚本注册的资源标识),例如下:RESOURCE-1=功能权限RESOURCE-10=业务流程新一代云ERP解决方案15四.特性说明1.标准化、系统化。采用标准RBAC模型,权限系统化。权限管理只能由少数特权用户完成(即担当公司管理员角色的用户,其他用户已经控制了不可能具有权限管理)。2.集中化管理。包括用户管理、角色管理、权限分配和权限控制,都可以由集团统一控制。3.上下级垂直管理。上级公司可以管理下级公司,可以为下级公司进行用户管理、角色管理、权限分配和权限控制。4.插件化:权限分配和权限查询,可以由插件实现。5.U8cloud不再直接为用户分配权限,废弃了用户组、用户关联公司以及快捷分配。1)角色外延了用户组。2)在U8cloud中,用户必须具有其他公司的角色,才间接表示用户关联了此公司。3)在U8cloud中,只需要角色分配多个公司,再分配公共权限,即可完成统一控制,减少了大量数据。6.权限的细粒度控制。1)U8cloud中,角色也可以控制是否启用权限。2)U8cloud中,集团也可以设置是否启用按钮权限。3)在U8cloud中,公司没有启用按钮权限,这种情况则无法分配按钮权限,这点能大大提高权限存取效率。新一代云ERP解决方案16五.附录5.1.引用的JAVADOC文档1.nc.itf.doc.api.DataPower数据权限接口,查找用户的权限,查找有权限的用户,查找有权限的角色等。2.nc.itf.doc.api.FuncPower方法摘要nc.vo.uap.rbac.power.PowerResultVOgetUserPower(nc.vo.uap.rbac.power.UserPowerQueryVOvoUserPowerQuery)根据UserPowerQueryVO所提供的资源标识、用户主键、组织类型、组织主键、公司主键,查询权限数据。booleanisUserEnablePowerControl(nc.vo.uap.rbac.power.UserPowerQueryVOvoUserPowerQuery)根据用户主键、资源标识、组织类型、组织主键、公司主键查询用户是否启用权限控制.booleanisUserHavePower(nc.vo.uap.rbac.power.UserPowerQueryVOvoUserPowerQuery,java.lang.StringresourceDataId)根据用户主键、资源标识、组织类型、组织主键、公司主键查询用户是否指定的资源记录标识具有权限.nc.vo.uap.rbac.RoleVO[]queryPowerRole(nc.vo.uap.rbac.power.PowerQueryByResVOvoQuery)根据资源标识、资源记录标识、组织类型、组织主键、公司主键查询有此资源记录权限的角色。nc.vo.sm.UserVO[]queryPowerUser(nc.vo.uap.rbac.power.PowerQueryByResVOvoQuery)根据资源标识、资源记录标识、组织类型、组织主键、公司主键查询有此资源记录权限的用户。新一代云ERP解决方案17功能权限接口,查找用户的功能权限,查找有权限的用户,查找有权限的主体账簿等。方法摘要nc.vo.sm.funcreg.FuncRegisterVO[]getUserFuncPower(java.lang.StringsUserid,java.lang.StringsCorpPK,java.lang.StringsOrgBookPK)获取用户的功能权限。java.lang.String[]queryCorpByUserAndFunc(java.lang.StringuserId,java.lang.StringfuncCode)根据用户主键和功能节点编码查询有权限的所有公司.java.lang.String[]queryPowerOrgBook(java.lang.Stringuserid,java.lang.StringsFuncode,java.lang.StringcorpPK)根据用户PK、功能节点code、公司PK,查询那些有此功能节点权限的主体账簿PK集合.java.lang.String[]queryPowerOrgByUserCorp(java.lang.Stringuserid,java.lang.StringpkCorp)根据用户和指定公司查找的有权限的所有主体账簿。nc.vo.sm.UserVO[]queryUserByFuncode(java.lang.StringpkCorp,java.lang.Stringfuncode,java.lang.StringsOrgBook)查询对某功能节点code具有权限且关联到某公司的所有用户。3.nc.itf.doc.api.Operator用户接口,查找用户信息,查找用户关联的业务员信息。方法摘要nc.vo.sm.UserVO[]getAllUsers()查询所有用户。新一代云ERP解决方案18nc.vo.bd.psndoc.PsnbasdocVOgetPsnbasdocByUserid(java.lang.StringuserId)根据用户主键获得对应的人员基本档案信息nc.vo.bd.b06.PsndocVOgetPsndocByUserid(java.lang.StringuserId,java.lang.StringpkCorp)根据用户主键获得对应的人员管理档案信息nc.vo.sm.UserVOgetUser(java.lang.StringuserPK)通过用户主键获取用户信息。nc.vo.sm.UserVOgetUserByCode(java.lang.StringuserCode)通过用户编码查找用户VO。nc.vo.bd.CorpVO[]getUserRelaCorps(java.lang.StringuserPK)查询用户所关联的公司(即用户能登录的公司)。nc.vo.uap.rbac.RoleVO[]getUserRole(java.lang.StringuserPK,java.lang.StringcorpPK)查询用户在指定公司具有的角色nc.vo.sm.UserVO[]getUsersByCorpAll(java.lang.StringpkCorp)通过公司主键返回所有能登录此公司的所有用户。nc.vo.sm.UserVO[]getUsersByCorpSelf(java.lang.StringcorpPK)通过公司PK查询该公司所有的用户5.2.引用的代码范例1.“收支项目”插件的nc.ui.uap.rbac.service.CostsubjTreeEditorController。packagenc.ui.uap.rbac.service;importnc.bs.framework.common.NCLocator;importnc.bs.logging.Logger;importnc.itf.uap.bd.accbank.IAccbankConst;importnc.itf.uap.bd.accbank.IAccbankPrivate;importnc.ui.uap.rbac.editor.AbstractResBusiService;importnc.ui.uap.rbac.editor.ResourceContext;importnc.ui.uap.rbac.editor.table.ITableResBusiService;importnc.vo.bd.b23.AccbankVO;新一代云ERP解决方案19importnc.vo.pub.ValueObject;/***@authorgss开户银行*/publicclassAccBankTableServiceextendsAbstractResBusiServiceimplementsITableResBusiService{/***/publicAccBankTableService(){super();}/**(non-Javadoc)*@seenc.ui.uap.rbac.editor.AbstractResBusiService#getSaveField()*/protectedStringgetSaveField(){return"pk_accbank";}/**(non-Javadoc)*@seenc.ui.uap.rbac.IResourceBusiServer#showFields()*/publicString[]showFields(){returnnewString[]{"bankacc","bankname"};}/**(non-Javadoc)*@seenc.ui.uap.rbac.IResourceBusiServer#showFieldNames()*/publicString[]showFieldNames(){returnnewString[]{nc.ui.ml.NCLangRes.getInstance().getStrByID("common","UC000-0004118")/*银行账号*/,新一代云ERP解决方案20nc.ui.ml.NCLangRes.getInstance().getStrByID("common","UC000-0004115")/*银行编码*/};}protectedbooleanisNeedReloadData(ResourceContextcontext){booleanisNeed=false;Stringold_pkCorp=null;booleanoldCommonPower=false;if(this.context!=null){old_pkCorp=this.context.getPk_corp();oldCommonPower=this.context.isCommonPower();}Stringnew_pkCorp=context.getPk_corp();old_pkCorp=old_pkCorp==null?"":old_pkCorp;new_pkCorp=new_pkCorp==null?"":new_pkCorp;if(!old_pkCorp.equals(new_pkCorp)||oldCommonPower!=context.isCommonPower()){isNeed=true;}returnisNeed;}protectedValueObject[]queryAllResDataByContext()throwsException{try{Stringpk_corp=context.getPk_corp();if(context.isCommonPower())pk_corp="0001";StringBufferstrCondition=newStringBuffer("bd_accbank.netbankflag<>").append(IAccbankConst.NETBANKFLAG_PERSON);if(pk_corp!=null&&pk_corp.length()>0){IAccbankPrivateiIAccbank=(IAccbankPrivate)NCLocator.getInstance().lookup(IAccbankPrivate.class.getName());新一代云ERP解决方案21returniIAccbank.queryAccbankVOsByCondition(pk_corp,strCondition.toString());}elsereturnnewAccbankVO[0];}catch(Exceptione){Logger.error(e.getMessage(),e);thrownewException("Erroroccurswhenqueryingbankdatas");/*查询公司所有的银行数据错误。*/}}publicObjectgetAttributeValue(Objectobj,StringfieldName){return((AccbankVO)obj).getAttributeValue(fieldName);}}2.“开户银行”插件的nc.ui.uap.rbac.service.AccBankTableService。packagenc.ui.uap.rbac.service;importnc.ui.bd.b28.CostsubjBO_Client;importnc.ui.uap.rbac.comp.ITreeNodeProvider;importnc.ui.uap.rbac.comp.selmode.INodeCheckMode;importnc.ui.uap.rbac.editor.ResourceContext;importnc.ui.uap.rbac.editor.tree.DefaultTreeResBusiService;importnc.ui.uap.rbac.service.mode.DigInRootCancelCurrentExcludeCommon;importnc.vo.bd.b28.CostsubjVO;publicclassCostsubjTreeEditorControllerextendsDefaultTreeResBusiService{protectedStringgetSaveField(){return"pk_costsubj";}publicITreeNodeProvidergetTreeNodeProvider(){returnnewCostsubjTreeNodeProvider();}publicINodeCheckModegetTreeSelectionMode(){新一代云ERP解决方案22returnnewDigInRootCancelCurrentExcludeCommon(this);}publicbooleansetResourceContext(ResourceContextcontext)throwsException{booleanisNeed=false;Stringold_pkCorp=null;booleanoldCommonPower=false;if(this.context!=null){old_pkCorp=this.context.getPk_corp();oldCommonPower=this.context.isCommonPower();}Stringnew_pkCorp=context.getPk_corp();old_pkCorp=old_pkCorp==null?"":old_pkCorp;new_pkCorp=new_pkCorp==null?"":new_pkCorp;if(!new_pkCorp.equals(old_pkCorp)||context.isCommonPower()!=oldCommonPower){if(context.isCommonPower()){totalVo=newCostsubjVO[0];}elseif(new_pkCorp.length()>0)totalVo=CostsubjBO_Client.queryAll(context.getPk_corp());elsetotalVo=newCostsubjVO[0];isNeed=true;}this.context=context;returnisNeed;}publicObjectgetAttributeValue(Objectobj,StringfieldName){return((CostsubjVO)obj).getAttributeValue(fieldName);}}新一代云ERP解决方案23新一代云ERP解决方案NewGenerationofCloudERPSolution用友网络科技股份有限公司YonyouNetworkTechCo.Ltd.