1概要

Activitiは、オープンソースのBPM(ビジネスプロセス管理)システムです。導入のために、私達のリンクをチェックしてください:/java-activiti[Guide to Activiti with Java]。

ActivitiとSpringフレームワークはどちらも独自のID管理を提供します。ただし、** 両方のプロジェクトを統合するアプリケーションでは、2つを1つのユーザー管理プロセスにまとめることができます。

以下では、これを実現するための2つの可能性を探っていきます。1つは、Spring Security用にActivitiがサポートするユーザサービスを提供することで、もう1つは、Spring SecurityユーザソースをActiviti ID管理に接続することです。


2 Mavenの依存関係

Spring BootプロジェクトでActivitiを設定するには、/spring-activitiというリンクをチェックしてください[以前の記事]。

activiti-spring-boot-starter-basicに加え、


https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22activiti-spring-boot-starterも必要になります。

-security%22[activiti-spring-boot-starter-security]依存関係:

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter-security</artifactId>
    <version>6.0.0</version>
</dependency>


3 Activiti

を使用したID管理

このシナリオでは、ActivitiスターターはすべてのRESTエンドポイントを

HTTP Basic

認証で保護するSpring Boot自動設定クラスを提供します。

  • 自動設定はクラス

    IdentityServiceUserDetailsS​​erviceの

    UserDetailsS​​ervice__ beanも作成します。

このクラスはSpringインタフェース

UserDetailsS​​ervice

を実装し、

loadUserByUsername()

メソッドをオーバーライドします。このメソッドは、指定された

id

を持つActiviti

User

オブジェクトを取得し、それを使用してSpring

UserDetails

オブジェクトを作成します。

また、Activiti

Group

オブジェクトは、Springユーザーロールに対応しています。

これが意味するのは、Spring Securityアプリケーションにログインするときに、Activitiの認証情報を使用するということです。


3.1. Activitiユーザーを設定する

まず、

IdentityServiceを使用して、メインの

@ SpringBootApplication

クラスに定義された

InitializingBean__にユーザーを作成しましょう。

@Bean
InitializingBean usersAndGroupsInitializer(IdentityService identityService) {
    return new InitializingBean() {
        public void afterPropertiesSet() throws Exception {
            User user = identityService.newUser("activiti__user");
            user.setPassword("pass");
            identityService.saveUser(user);

            Group group = identityService.newGroup("user");
            group.setName("ROLE__USER");
            group.setType("USER");
            identityService.saveGroup(group);
            identityService.createMembership(user.getId(), group.getId());
        }
    };
}


  • これはSpring Securityによって使用されるので、

    Group

    オブジェクト

    name



    “ ROLE

    X”



    **

    .

    __の形式でなければならないことに気付くでしょう。


3.2. Springのセキュリティ設定

HTTP基本認証の代わりに別のセキュリティ設定を使用したい場合は、まず自動設定を除外する必要があります。

@SpringBootApplication(
  exclude = org.activiti.spring.boot.SecurityAutoConfiguration.class)
public class ActivitiSpringSecurityApplication {
   //...
}

次に、

IdentityServiceUserDetailsS​​ervice

を使用してActivitiデータソースからユーザーを取得する独自のSpring Security設定クラスを提供します。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private IdentityService identityService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
      throws Exception {

        auth.userDetailsService(userDetailsService());
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new IdentityServiceUserDetailsService(
          this.identityService);
    }

   //spring security configuration
}


4 Spring Security

を使用したID管理

Spring Securityでユーザー管理がすでに設定されており、Activitiをアプリケーションに追加したい場合は、ActivitiのID管理をカスタマイズする必要があります。

この目的のために、私達が拡張しなければならない2つの主要なクラスがあります:

ユーザーとグループを処理する

UserEntityManagerImpl



GroupEntityManagerImpl

それぞれを詳しく見てみましょう。


4.1.

UserEntityManagerImpl


を拡張する


UserEntityManagerImpl

クラスを拡張する独自のクラスを作成しましょう。

public class SpringSecurityUserManager extends UserEntityManagerImpl {

    private JdbcUserDetailsManager userManager;

    public SpringSecurityUserManager(
      ProcessEngineConfigurationImpl processEngineConfiguration,
      UserDataManager userDataManager,
      JdbcUserDetailsManager userManager) {

        super(processEngineConfiguration, userDataManager);
        this.userManager = userManager;
    }

   //...
}

このクラスには上記の形式のコンストラクタとSpring Securityのユーザマネージャが必要です。今回のケースでは、データベースを使用した__UserDetailsManagerを使用しました

  • オーバーライドしたい主なメソッドは、ユーザーの検索を処理するものです。


findById()メソッドは、

JdbcUserDetailsManager

を使用して

UserDetails

オブジェクトを見つけ、それを

User__オブジェクトに変換します。

@Override
public UserEntity findById(String userId) {
    UserDetails userDetails = userManager.loadUserByUsername(userId);
    if (userDetails != null) {
        UserEntityImpl user = new UserEntityImpl();
        user.setId(userId);
        return user;
    }
    return null;
}

次に、

findGroupsByUser()

メソッドは、ユーザーのすべてのSpring Security権限を検索し、

Group

オブジェクトの

List

を返します。

public List<Group> findGroupsByUser(String userId) {
    UserDetails userDetails = userManager.loadUserByUsername(userId);
    if (userDetails != null) {
        return userDetails.getAuthorities().stream()
          .map(a -> {
            Group g = new GroupEntityImpl();
            g.setId(a.getAuthority());
            return g;
          })
          .collect(Collectors.toList());
    }
    return null;
}


findUserByQueryCriteria()

メソッドは、複数のプロパティを持つ

UserQueryImpl

オブジェクトに基づいています。これらはSpring Securityに対応するものであるため、グループIDとユーザーIDを抽出します。

@Override
public List<User> findUserByQueryCriteria(
  UserQueryImpl query, Page page) {
   //...
}

このメソッドは、

UserDetails

オブジェクトから

User

オブジェクトを作成することにより、上記の方法と似た原則に従います。完全な実装については最後のGitHubリンクを見てください。

同様に、

findUserCountByQueryCriteria()

メソッドがあります。

public long findUserCountByQueryCriteria(
  UserQueryImpl query) {

    return findUserByQueryCriteria(query, null).size();
}

パスワードの検証はActivitiによって行われないため、

checkPassword()

メソッドは常にtrueを返す必要があります。

@Override
public Boolean checkPassword(String userId, String password) {
    return true;
}

ユーザーの更新を扱う方法など、他の方法ではSpring Securityが処理するので例外をスローします

public User createNewUser(String userId) {
    throw new UnsupportedOperationException("This operation is not supported!");
}


4.2.

GroupEntityManagerImpl


を拡張する


SpringSecurityGroupManager

は、ユーザーグループを扱う点を除いて、ユーザーマネージャクラスと似ています。

public class SpringSecurityGroupManager extends GroupEntityManagerImpl {

    private JdbcUserDetailsManager userManager;

    public SpringSecurityGroupManager(ProcessEngineConfigurationImpl
      processEngineConfiguration, GroupDataManager groupDataManager) {
        super(processEngineConfiguration, groupDataManager);
    }

   //...
}

ここでオーバーライドする主なメソッドは

findGroupsByUser()

メソッドです。

@Override
public List<Group> findGroupsByUser(String userId) {
    UserDetails userDetails = userManager.loadUserByUsername(userId);
    if (userDetails != null) {
        return userDetails.getAuthorities().stream()
          .map(a -> {
            Group g = new GroupEntityImpl();
            g.setId(a.getAuthority());
            return g;
          })
          .collect(Collectors.toList());
    }
    return null;
}

このメソッドは、Spring Securityのユーザの権限を取得し、それらを

Group

オブジェクトのリストに変換します。

これに基づいて、

findGroupByQueryCriteria()

メソッドと

findGroupByQueryCriteriaCount()

メソッドをオーバーライドすることもできます。

@Override
public List<Group> findGroupByQueryCriteria(GroupQueryImpl query, Page page) {
    if (query.getUserId() != null) {
        return findGroupsByUser(query.getUserId());
    }
    return null;
}

@Override
public long findGroupCountByQueryCriteria(GroupQueryImpl query) {
    return findGroupByQueryCriteria(query, null).size();
}

グループを更新する他のメソッドをオーバーライドして例外をスローすることができます。

public Group createNewGroup(String groupId) {
    throw new UnsupportedOperationException("This operation is not supported!");
}


4.3. プロセスエンジン構成

2つのIdentity Managerクラスを定義したら、それらを構成に関連付ける必要があります。

春初心者は私たちのために

SpringProcessEngineConfiguration

を自動設定します。これを変更するために、__InitializingBeanを使用できます。

@Autowired
private SpringProcessEngineConfiguration processEngineConfiguration;

@Autowired
private JdbcUserDetailsManager userManager;

@Bean
InitializingBean processEngineInitializer() {
    return new InitializingBean() {
        public void afterPropertiesSet() throws Exception {
            processEngineConfiguration.setUserEntityManager(
              new SpringSecurityUserManager(processEngineConfiguration,
              new MybatisUserDataManager(processEngineConfiguration), userManager));
            processEngineConfiguration.setGroupEntityManager(
              new SpringSecurityGroupManager(processEngineConfiguration,
              new MybatisGroupDataManager(processEngineConfiguration)));
            }
        };
    }

ここでは、既存の

processEngineConfiguration

がカスタムIDマネージャを使用するように変更されています。

現在のユーザーをActivitiに設定したい場合は、次のメソッドを使用できます。

identityService.setAuthenticatedUserId(userId);

これは

ThreadLocal

プロパティを設定するので、値はスレッドごとに異なります。


5結論

この記事では、ActivitiとSpring Securityを統合する2つの方法について説明しました。

完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-activiti[over on GitHub]にあります。