知识大全 使用JBoss jBPM实现流程访问和执行的授权

Posted 命令

篇首语:知识的领域是无限的,我们的学习也是无限期的。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 使用JBoss jBPM实现流程访问和执行的授权相关的知识,希望对你有一定的参考价值。

使用JBoss jBPM实现流程访问和执行的授权  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  当今常见的BPM趋势是集中化整个公司或公司内大部门的BPM执行 这意味着 单个BPM服务器(集群)运行着整个公司的许多流程定义 这种方式的挑战在 于 虽然BPM引擎(包括jBPM)提供了对于任务访问的授权 但它们一般都不支持这些功能的授权 流程定义的查看和删除 流程实例的启动 结束 查看和删除等 在这篇文章中 我们将描述如何对jBPM引擎进行扩展 (基于jBPM )来实现这一功能

  整体实现方法

  整个实现方式相当直接了当——对于每个流程定义引入一组可以授权的用户/用户组(类似任务定义) 作用于定义 实例和给定流程的历史 此外 我们还想对给 定的用户/用户组支持多重授权级别——目前我们打算引入 个角色 starter 和 user 这里的 starter 是允许对流程定义/实例 /历史进行任何操作的角色 而 user 角色的权限仅限于查询流程/历史

  这种方式的实现需要对jBPM进行以下改造

  ◆流程定义

  给流程定义增加流程访问权限

  ◆流程部署

  扩展当前的流程部署器 增加流程授权定义的解析和流程访问列表的生成

  引入额外的类/数据库表 存放每个流程定义的访问权限

  ◆流程执行(Execution)

  引入已授权命令(authorized mand)——要求用户经过授权才能执行的命令

  修改现有的jBPM中我们期望基于当前用户证书进行授权的部分 这包括启动 结束和删除流程实例 以及删除部署定义

  修改现有的jBPM查询 考虑现有用户的证书 这包括部署和流程定义查询 流程实例查询 以及历史流程实例 活动和细节的查询

  除了以上更改 我们还想扩展流程实例查询 好让用户可以通过指定某些流程变量的值来缩小查询结果 这种搜索的一个常见情况就是查询 由我启动的 流程 为 了确保这种查询总是可用 我们更改了启动流程实例命令的实现 显式地把当前用户ID加到了流程变量值的集合中

  最后 为了支持多种用户认证方法 我们实现了一个自定义的身份会话 它支持用程序来设置和访问当前用户的证书 其目的在于 把用户证书(ID和参与的组) 的获得和jBPM运行时对这种信息的使用分离开来

  我们的实现利用了非常强大和灵活的jBPM 的配置机制 它让我们可以

  通过扩展现有jBPM类 最小化了自定义代码的数量 只实现我们扩展所需的额外功能

  将我们的扩展实现成可以与jBPM 类库一起使用的单独jar包 无需对现有库进行任何改变

  在深入我们的实现细节之前 我们首先要讨论一下我们大量使用的jBPM 的配置

  jBPM 的配置机制

  jBPM的基础是流程虚拟机(PVM)[ ] 它建立在自定义的依赖注入实现之上 依赖注入由非常强大的 基于XML的配置机制控制 这种机制用于创建标签和预定义接口相关的特定实现之间的绑定 (binding)

  这种机制的核心是jbpm wire bindings xml文件 它描述了[ ] jBPM PVM的主要组件 包括

  ◆基本类型

  ◆对象及引用

  ◆环境引用

  ◆Hibernate绑定

  ◆会话

  ◆服务

  ◆部署器

  ◆拦截器

  ◆等

  该文件是jBPM分发包的一部分 如果用户想增加自己的绑定(binding) 他可以创建jbpm user wire bindings xml描述 它们 而不用修改jbpm wire bindings xml文件

  这两个文件会被jBPM PVM在启动时读入并解析 为定义在jbpm cfg xml中的基础PVM执行(execution)配置而服务 jbpm cfg xml一般会包含 多个部分 描述了PVM执行的特定组件的配置

  jBPM PVM由一组提供PVM功能的服务组成[ ] 主要的PVM服务包括

  ◆仓储服务 提供一组查看和管理部署仓储的方法

  ◆执行服务 提供一组查看和管理运行中流程执行(execution)的方 法

  ◆管理服务 提供一组查看和管理工作(job)的方法

  ◆任务服务 提供一组查看和管理用户任务(task)的方法

  ◆历史服务 提供一组访问运行中和已完成流程执行的历史信息的方法

  这组可用服务和实现这些服务的类(使用前面说的绑定)被配置成流程引擎的上下文

  服务执行被实现成一组命令(mand) 它们作为服务方法执行的一部分被调用 命令的实际执行由命令服务控制

  命令服务在命令服务上下文中被配置成一组拦截器 实现横切关注点 环绕(around)命令调用(命令执行管线) 缺省的jBPM分发包在命令执行管线中 携带了以下拦截器

  ◆重试(Retry)拦截器负责重试命令执行

  ◆环境(Environment)拦截器负责在必要时把jBPM上下文注入命 令执行中

  ◆事务(Transaction)拦截器负责介入命令调用的事务边界划分

  拦截器是将jBPM移植到不同环境以及引入其他横切关注点的核心机制

  命令执行一般会利用环境 它也是可配置的 典型的环境组件有

  ◆仓储会话

  ◆DB会话

  ◆消息会话

  ◆定时器会话

  ◆历史会话

  ◆邮件会话

  可以添加其他会话来扩展PVM的功能

  最后 部署管理器配置允许指定一组部署器 它们依次执行 把业务流程部署到PVM 这种方法使得扩展流程定义可以通过实现额外的部署步骤完成 无需覆蓋 jBPM分发包自带的部署器

  整个PVM的架构如图 示

  图 PVM架构

  在流程定义中引入授权

  我们在图 中看到 可以给流程定义添加任意属性 利用这种扩展选项 我们现在定义以下流程属性 描述授权策略

  ◆starter users 具有 starter 角色的用户列表

  ◆starter groups 具有 starter 角色的组列表

  ◆user users 具有 user 角色的用户列表

  ◆user groups 具 有 user 角色的组列表

  每个属性的值是逗号分隔的组/用户id列表

  图 流程定义模式

  此外 我们还定义了一个特殊的用户类型 any 和两个用户组 all 和 admin 任何用户 不论其真实ID是什么 都是 any 用 户 任何组 不论其ID是什么 也都是 all 最后 admin 组的成员被认为是任意组的成员

  流程授权定义由以下规则驱动

  ◆如果user users和user groups都未被指定 则user users= all

  ◆如果 starter users和starte groups都未被指定 则流程用户被额外地分配 starter 角色

  按照这个规则 清单 中的流程可以被任何人启动和使用

   <process package= navteq jbpm

            key= NO_AUTHORIZATION

            name= Test Authorization not required

            version=

            xmlns= >

       <start g= name= start >

           <transition to= end />

       </start>

       <end g= name= end />

   </process>

  

  清单 没有授权信息的流程定义

  清单 的流程可以被mark或tomcat组中的任何人使用和启动

   <process package= navteq jbpm

            key= AUTHORIZATION

            name= Test Authorization Required

            version=

            xmlns=

            user users= mark

            user groups= tomcat >

       <start g= name= start >

           <transition to= end />

       </start>

       <end g= name= end />

   </process>

  清单 具有用户授权信息的流程定义

  我们引入了一个新类 ACL 针对给定流程 (processDefinitionID processDefinitionKey DeploymentID) 它包含一个单独的访问列表(用户或 组 以及类型) 同时还引入了相应的Hibernate定义

  图 中 清单 的流程部署为具有两个角色( user 和 starter )的用户 any 创建了 个ACL 而在图 中 清单 的流程部署将创建 个 用户 mark 和组 tomcat 每个都具有 个角色 user 和 starter

  图 无授权信息的流程的ACL

  图 有用户授权信息的流程的ACL

  这些ACL的生成是通过引入额外的部署器完成的 它将在 标准 jBPM部署器之后运行 抽取上面描述的授权属性 为给定流程构建ACL

  保护jBPM命令

  我们采用了一种通用的方法来保护jBPM命令 包括实现用于定义命令所需授权信息的自定义的注解 以及处理这个注解的自定义的授权会话(命令拦截器)实现

  授权注解(清单 )可以指定所需的用户角色和表示某个流程的方法

   @Retention(value=RetentionPolicy RUNTIME)

   @Target(value=ElementType METHOD)

   public @interface AuthorizedCommand

       /** Access type */

       public String role();

       String key();

  

  

  清单 授权注解

  对于某个流程 用户角色 starter 或 user 指向某个用户应该拥有的角色[ ] 由于不同命令既可以引用部署ID 也可以引用流程ID或者流程键值 因此注解支持多种指定键值的方式 允许将合适的引用指定为键值

  清单 的授权拦截器检查是否有命令的方法被授权注解修饰 如果有 则执行适当的查询 确定出哪些用户和用户组集合被授权给了这个命令 然后检查当前用户是 否属于他们

   …………

  

   @SuppressWarnings( unchecked )

   public void checkPermission(Command<?> mand EnvironmentImpl environment)

       environment setAuthenticatedUserId(environment get(AuthorizationIdentitySession class) getAuthenticatedUserId());

       for( Method method : mand getClass() getMethods())

           AuthorizedCommand sc = method getAnnotation(AuthorizedCommand class);

           if(sc != null)

               log debug( Checking Class based Secured Function );

               String ID = environment get(AuthorizationIdentitySession class) getAuthenticatedUserId();

               Object value = null;

               try

                   log debug( Checking authorization: + mand getClass() getName());

                   Session session = environment get(SessionImpl class);

                   value = method invoke(mand (Object[])null);

                   Query uQ = session createQuery(userQuery get(sc key()))

                   setString( role sc role()) setString( value (String) value);

                   Query gQ = session createQuery(groupQuery get(sc key()))

                   setString( role sc role()) setString( value (String) value);

                   List<String> userIds = (List<String>)uQ list();

                   List<String> groups = (List<String>)gQ list();

                   if(!isAuthorized(environment userIds groups))

                       throw new AccessControlException(ID+ attempted access to ProcessDefinition # +value);

               catch (IllegalArgumentException e)

                   log error( Caught + IllegalArgumentException class e);

                   throw new AccessControlException(ID+ attempted access to ProcessDefinition # +value);

               catch (IllegalAccessException e)

                   log error( Caught + IllegalAccessException class e);

                   throw new AccessControlException(ID+ attempted access to ProcessDefinition # +value);

               catch (InvocationTargetException e)

                   log error( Caught + InvocationTargetException class e);

                   throw new AccessControlException(ID+ attempted access to ProcessDefinition # +value);

              

          

      

       return;

  

  

   ……………………

  

   public boolean isAuthorized(EnvironmentImpl env List<String> authorizedUserIds List<String> authorizedGroupIds)

       AuthorizationIdentitySession identitySession = env get(AuthorizationIdentitySession class);

       if (antains(AuthorizationIdentitySession ANONYMOUS_USER_ID))

           return true;

       if (antains(identitySession getAuthenticatedUserId()) )

           return true;

       //check if any of userGroups is an authorized group   if so then return true

       List<Group> groups = identitySession findGroupsByUser(identitySession getAuthenticatedUserId());

       for(Group group : groups)

           String g = group getId();

           //admin is allowed to execute any mand

           if(g equals(AuthorizationIdentitySession ADMINISTRATORS_GROUP))

               return true;

           if(auntains(g))

               return true;

      

       return false;

  

  

  清单 授权拦截器

  为了保护命令实现 我们创建了一个新类 它扩展了现有的命令 增加了一个带注解的方法(清单 ) 返回给定命令可用的键值

   @AuthorizedCommand(role = ACL STARTER key = NavteqAuthorizationSession PROCESSID)

   public String getProcessDefinitionKey()

      return processDefinitionId;

  

  清单 给启动流程实例命令引入授权信息

  根据所提议的方法 我们对下列命令进行了注解

  ◆删除部署

  ◆启动流程实例

  ◆启动最近的流程实例

  ◆结束流程实例

  ◆删除流程实例

  扩展查询

  引入授权意味着查询结果应该只返回用户被授权查看的信息[ ] 这可以通过扩展现有查询的where语句实现(清单 )

   //check authorization

   String userId = EnvironmentImpl getCurrent() getAuthenticatedUserId();

   List<Group> userGroups = EnvironmentImpl getCurrent() get(IdentitySession class) findGroupsByUser(userId);

  

   hql append( + ACL class getName() + as acl );

   appendWhereClause( acl deployment=deployment and acl type= +

                     ACL STARTER +

                     hql);

   appendWhereClause( ((acl userId in +

                     Utils createHqlUserString(userId) +

                     ) or +

                     (acl groupId in +

                     Utils createHqlGroupString(userGroups) + ))

                     hql);

  清单 为流程定义查询提供授权支持的额外where语句

  额外的where语句是通过扩展现有查询实现和覆蓋hlq方法实现的

  按照这种方法 扩展了以下查询

  ◆部署查询

  ◆流程定义查询

  ◆流程实例查询

  ◆历史流程实例查询

  ◆历史活动 查询

  ◆历史细节查询

  为了能够增加字符串实例变量 以缩小查询结果 我们还额外扩展了一个流程实例查询

  支持多种用户管理方式

  以上给出的实现依赖使用执行环境来获得当前用户ID和使用IdentitySession来获得用户组成员关系 jBPM分发包提供了这个接口的 个实现

  ◆IdentitySessionImpl 基于jBPM的用户/组数据库

  ◆JBossIdmIdentitySessionImpl 基于JBoss Identity IDM组件

  不同于大量依赖其他技术的实现 对于我们的实现 我们决定把用户ID/组的获取同这些信息的保存分离开来 使之可以被其他的jBPM实现利用(图 )

  图 用户管理实现

  为了确保在设定和重新设定用户证书的时候环境是可用的 我们把这两个操作实现成了命令(清单 ) 这样 借助jBPM命令执行服务就可以正确设置执行环境

   public static class SetPrincipalCommand extends AbstractCommand<Void>

       private static final long serialVersionUID = L;

       private String userId;

       private String[] groups;

       public SetPrincipalCommand(String u String groups)

           this userId=u; this groups=groups;

      

       public Void execute(Environment environment) throws Exception

           environment get(AuthorizationIdentitySession class) setPrincipal(userId groups);

           return null;

      

  

  

   public static class ResetPrincipalCommand extends AbstractCommand<Void>

       private static final long serialVersionUID = L;

       public Void execute(Environment environment) throws Exception

           environment get(AuthorizationIdentitySession class) reset();

           return null;

      

  

  把新命令和查询引入到jBPM执行中

  由于jBPM并没有提供任何配置 命令 服务 关系的支持 为了能改变给定服务中的命令 就必须使用调用新命令的新服务实现覆蓋旧实现 清单 给出了一个使用新命令服务覆蓋历史服务的例子

   public class NavteqHistoryServiceImpl extends HistoryServiceImpl

       @Override

       public HistoryActivityInstanceQuery createHistoryActivityInstanceQuery()

         return new AuthorizedHistoryActivityInstanceQueryImpl(mandService);

      

  

       @Override

       public HistoryDetailQuery createHistoryDetailQuery()

           return new AuthorizedHistoryDetailQueryImpl(mandService);

      

  

       @Override

       public HistoryProcessInstanceQuery createHistoryProcessInstanceQuery()

           return newAuthorizedHistoryProcessInstanceQuery(mandService);

      

  

  

  清单 在历史服务中引入授权命令

  总结

cha138/Article/program/Java/ky/201311/28771

相关参考

知识大全 编程方式部署jBPM工作流

编程方式部署jBPM工作流  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  本文介绍了编程方式部署

知识大全 spring+hibernate+jbpm整合成功

  终于搞定了在此感谢chenjin的指点  从日整合失败后这块就一直是我的心病我甚至都跑去了去发了一个帖这还是我第一次用英文问问题呢  最后的配置结果是  hibernatecfgxmljbpmcf

知识大全 人力资源与行政后勤工作执行流程 pdf文件 。 谢谢

求人力资源与行政后勤工作执行流程pdf文件。谢谢!,急求人力资源与行政后勤工作执行流程.pdf或者word版本谢谢人力资源与行政后勤工作执行流程谢谢人力资源与行政后勤工作执行流程提取码见私信求《人力资

知识大全 Oracledelete执行过程的流程介绍

Oracledelete执行过程的流程介绍  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  以下的

知识大全 Asp.Net页面执行流程分析

Asp.Net页面执行流程分析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在我的上一篇文章中

知识大全 为tomcat页面设置访问权限

  在web应用中对页面的访问控制通常通过程序来控制流程为登录>设置session>访问受限页面时检查session是否存在如果不存在禁止访问  对于较小型的web应用可以通过tomcat

知识大全 接口访问

  使用public关键字时它意味着紧随在public后面的成员声明适用于所有人特别是适用于使用库的客户程序员假定我们定义了一个名为dessert的包其中包含下述单元(若执行该程序时遇到困难请参考第章

知识大全 php“内存位置访问无效”错误的解决办法

  配置环境如下  WinSP+IIS+php+mysqla+zenda+PhpMyAdminPHP执行方式:isapiMysql为手动安装  关于“内存位置访问无效”的错误解决办法与步骤(一些部份无

知识大全 面向方面编程(AOP)和Jboss

面向方面编程(AOP)和Jboss  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  概述  面向方

知识大全 在JBoss中配置多个数据库和数据源

在JBoss中配置多个数据库和数据源  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  JBoss是