Activiti 7 如何接入自己系統的身份管理


一、 官方示例

首先,官網給出了簡單了demo 示例:https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplicationConfiguration.java#L26

建議大家將完成的demo下載下來仔細看下。下面說下其主要思路

 

1 SecurityUtil

@Component
public class SecurityUtil {


    @Autowired
    private UserDetailsService userDetailsService;


    public void logInAs(String username) {


        UserDetails user = userDetailsService.loadUserByUsername(username);
        if (user == null) {
            throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
        }


        SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return user.getAuthorities();
            }


            @Override
            public Object getCredentials() {
                return user.getPassword();
            }


            @Override
            public Object getDetails() {
                return user;
            }


            @Override
            public Object getPrincipal() {
                return user;
            }


            @Override
            public boolean isAuthenticated() {
                return true;
            }


            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {


            }


            @Override
            public String getName() {
                return user.getUsername();
            }
        }));
        org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username

此類關鍵代碼 一

 SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return user.getAuthorities();

認證上下文中設置了Authentication 對象,此對象返回了認證者的權限Authorities集合,后面會拿這個結果做判定,如果沒有 ROLE_ACTIVITI_USER 將會拋出異常,提示無法訪問。

此類關鍵代碼 二

org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);

  往 Authentication 上下文中設置了登錄者,注意了,此處的Authentication 和前面Spring SecurityContextHolder 中的不一樣,二者包名不一樣。activiti 中 Authentication中的線程變量用於后面的用戶信息獲取。比如設置發起人,當前用戶的任務等。

2 配置類

@Bean
public UserDetailsService myUserDetailsService() {


    InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();


    String[][] usersGroupsAndRoles = {
            {"system", "password", "ROLE_ACTIVITI_USER"},
            {"admin", "password", "ROLE_ACTIVITI_ADMIN"},
    };


    for (String[] user : usersGroupsAndRoles) {
        List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
        logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
        inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
                authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
    }




    return inMemoryUserDetailsManager

注入了 InMemoryUserDetailsManager 這個用戶服務,新建了兩個用戶 system ,admin,具備相應的角色,請注意 ROLE_ACTIVITI_ADMIN 的用戶將無法訪問調用相關的api 。

 

二、 接入自定義身份

 

根據以上兩點,我們就可以改造,並接入自己的身份系統。

 

1 用戶

1 編寫 ActivitiUserDetailsManager

UserDetailsService 將會注入我們自己的身份服務ActivitiUserDetailsManager。其實現我們仿造InMemoryUserDetailsManager 類即可,關鍵代碼是重寫 如下方法:

@Override
    public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
        BizUserEntity bizUser = userService.getBizUserById(userId);
        return new User(bizUser.getName(), "", Collections.singletonList(new SimpleGrantedAuthority("ROLE_ACTIVITI_USER")));
    }

其中

BizUserEntity bizUser = userService.getBizUserById(userId);

這個是自己業務中身份服務查詢方法,並且將此對象轉換為如下用戶

org.springframework.security.core.userdetails.User;

並且具備ROLE_ACTIVITI_USER 這個角色。

 

2 配置類

和demo一樣,注入UserDetailsService 即可。

@Bean
public UserDetailsService activitiUserDetailsService() {
    return new ActivitiUserDetailsManager(userService,groupManager);
}

   此次的參數 userService,groupManager 就是自己業務系統的用戶/組管理服務,我這里是通過構造器傳入進去的,你也可以通過其他方式實現注入。說白了就是ActivitiUserDetailsManager 這個類呢對你自己的userService 又作了一層簡單的包裝,這樣可以做到和工作流的用戶服務解耦。

2 用戶組

 等等,以上的案例只是說明了用戶查詢,但是用戶組呢?其實activiti 7 中,有默認的實現

org.activiti.core.common.spring.identity.ActivitiUserGroupManagerImpl

其中,有兩個最重要的方法:獲取用戶組,獲取用戶角色

public List<String> getUserGroups(String username) {
    return (List)this.userDetailsService.loadUserByUsername(username).getAuthorities().stream().filter((a) -> {
        return a.getAuthority().startsWith("GROUP_");
    }).map((a) -> {
        return a.getAuthority().substring(6);
    }).collect(Collectors.toList());
}


public List<String> getUserRoles(String username) {
    return (List)this.userDetailsService.loadUserByUsername(username).getAuthorities().stream().filter((a) -> {
        return a.getAuthority().startsWith("ROLE_");
    }).map((a) -> {
        return a.getAuthority().substring(5);
    }).collect(Collectors.toList());
}

這里其實也是通過userDetailsService 這個用戶查詢來做的,並且 是通過前綴匹配去查詢 ROLE_ , GROUP_ 的字符串,到這里也就不難理解demo中如下代碼了

{"system", "password", "ROLE_ACTIVITI_USER"},
{"admin", "password", "ROLE_ACTIVITI_ADMIN"}

因此,仿造ActivitiUserGroupManagerImpl 的實現,新建 ActivitiGroupManagerImpl 實現

org.activiti.api.runtime.shared.identity.UserGroupManager

重寫相關的方法即可。值得注意的一點是,需要加上@Primary這個注解

 

 因為 默認的 ActivitiUserGroupManagerImpl 也是自動交給spring初始化了,加上@Primary 就是告訴spring 當有多個 實現類shi,用ActivitiGroupManagerImpl 這個類。

到此,就完全接入自己的身份系統了,包含用戶和用戶組的能力。對於 activiti7 以下的版本,實現會有很大的差異,但是官方文檔給出了解決方案,參見如下:

https://www.activiti.org/userguide/index.html#advanced.custom.session.manager

 

https://my.oschina.net/woniuyi/blog/4714756


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM