首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JBoss jBPM 4.3 流程授權擴充實作:從定義到執行的完整存取控制

     編輯:Java 相關知識

企業級 BPM 部署常集中多流程於單一 jBPM 叢集,原生僅支援任務層級授權,缺乏流程定義/實例/歷史的檢視、啟動、刪除權限控制。本文詳細記錄基於 jBPM 4.3 核心 PVM (Process Virtual Machine) 的授權擴充實作:流程屬性宣告、ACL 持久化、命令攔截授權、查詢擴展、多身份來源支援。

授權模型設計

  • 兩大角色:starter (完整權限:啟動/刪除/檢視定義/實例/歷史) 與 user (唯讀檢視)。
  • 四種主體清單:starter-users, starter-groups, user-users, user-groups,流程定義屬性以逗號分隔存放。
  • 特殊主體:any (所有使用者)、all (所有群組)、admin (超級管理員群組,隱含 all 權限)。
  • 預設規則:未指定 user-* 視同 user-users="all";未指定 starter-* 視同所有流程使用者自動獲得 starter 角色。

流程定義範例


<process key="AUTH_DEMO" name="需授權流程"
         user-users="alice,bob" user-groups="analysts"
         starter-users="charlie" starter-groups="managers">
  <start name="s" g="10,10,48,48"><transition to="end"/></start>
  <end name="end" g="10,100,48,48"/>
</process>

核心擴充點實作

1. ACL 實體與持久化


@Entity @Table(name="JBPM4_PROC_ACL")
public class ACL {
    public static final String STARTER = "starter";
    public static final String USER = "user";
    @Id @GeneratedValue Long id;
    String deploymentId; String processDefinitionId; String processDefinitionKey;
    String principalId; // userId 或 groupId
    String principalType; // "user" 或 "group"
    String role; // "starter" 或 "user"
}

部署時由額外部署器 (部署器鏈最後) 解析流程屬性,批次建立 ACL 記錄。

2. 命令授權攔截器

  • 自訂註解 @AuthorizedCommand(role, key) 標註需授權的命令方法 (如 getProcessDefinitionId())。
  • 攔截器在命令執行管線中 (EnvironmentInterceptor 之後、TransactionInterceptor 之前) 執行:

public void checkPermission(Command cmd, EnvironmentImpl env) {
    String userId = env.get(AuthIdentitySession.class).getAuthenticatedUserId();
    for (Method m : cmd.getClass().getMethods()) {
        AuthorizedCommand ann = m.getAnnotation(AuthorizedCommand.class);
        if (ann != null) {
            Object keyVal = m.invoke(cmd); // 取得 deploymentId/processDefinitionId...
            List allowedUsers = queryAclUsers(keyVal, ann.role());
            List allowedGroups = queryAclGroups(keyVal, ann.role());
            if (!isAuthorized(env, allowedUsers, allowedGroups))
                throw new AccessControlException(userId + " denied access to " + keyVal);
        }
    }
}

boolean isAuthorized(EnvironmentImpl env, List users, List groups) {
    AuthIdentitySession idSess = env.get(AuthIdentitySession.class);
    if (users.contains(AuthIdentitySession.ANY)) return true;
    if (users.contains(idSess.getAuthenticatedUserId())) return true;
    for (Group g : idSess.findGroupsByUser(idSess.getAuthenticatedUserId())) {
        if (g.getId().equals(AuthIdentitySession.ADMIN) || groups.contains(g.getId()))
            return true;
    }
    return false;
}

3. 受保護命令清單

  • 刪除部署
  • 啟動流程實例 / 啟動最新版本流程實例
  • 結束流程實例 / 刪除流程實例

各命令子類化並加上 @AuthorizedCommand(role=STARTER, key=PROCESS_DEFINITION_ID) 註解。

4. 查詢授權擴展 (HQL Where 條件注入)


// 部署/流程定義/流程實例/歷史查詢通用擴展
String userId = env.getAuthenticatedUserId();
List userGroups = env.get(IdentitySession.class).findGroupsByUser(userId);

hql.append(", ACL acl");
hql.append(" WHERE acl.deployment = deployment AND acl.role = 'starter'");
hql.append(" AND (acl.principalId IN (:userIds) OR acl.principalId IN (:groupIds))")
   .setParameterList("userIds", buildUserList(userId))
   .setParameterList("groupIds", buildGroupList(userGroups));

透過擴展查詢實作類並覆寫 hql() 方法注入條件。

5. 流程實例變數自動注入 (支援「我啟動的」查詢)

啟動命令執行時,顯式將 currentUserId 寫入流程變數,查詢時可直接過濾。

6. 可插拔身份會話

  • AuthIdentitySession 介面定義 getAuthenticatedUserId(), findGroupsByUser(), setPrincipal()/reset()。
  • 實作與 jBPM 內建 IdentitySessionImpl、JBossIdmIdentitySessionImpl 解耦,支援 LDAP、SSO、自定義用戶存儲。
  • SetPrincipalCommand/ResetPrincipalCommand 納入命令管線,確保環境可用時設定主體。

配置整合 (jbpm.user.wire.bindings.xml)


<bean name="jbpm.command.service.interceptors" class="java.util.ArrayList">
  <constructor-arg>
    <list>
      <ref bean="retryInterceptor"/>
      <ref bean="environmentInterceptor"/>
      <ref bean="authorizationInterceptor"/> <!-- 新增 -->
      <ref bean="transactionInterceptor"/>
    </list>
  </constructor-arg>
</bean>
<bean name="authorizationInterceptor" class="com.navteq.jbpm.auth.AuthorizationInterceptor"/>
<bean name="authIdentitySession" class="com.navteq.jbpm.auth.AuthIdentitySessionImpl"/>

服務實作類 (如 NavteqHistoryServiceImpl) 覆寫工廠方法回傳授權版查詢物件。

架構優勢總結

  1. 零侵入 jBPM 核心:僅透過 jbpm.user.wire.bindings.xml 註冊擴充 Bean,升級相容。
  2. 語言中立:作用於 PVM 層,jPDL、BPMN2 等所有語言自動受益。
  3. 細粒度控制:部署/定義/實例/歷史各層級獨立授權。
  4. 身份來源解耦:支援任意用戶/群組後端,無綁定 jBPM 內建用戶表。

此擴充已於生產環境穩定運行,支援數百流程定義、數萬實例的多租戶授權場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved