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

關於 activiti 7 的相關文章,可以參見:

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

所以,我們知道了 activiti 7 沒有身份管理相關的表了,其能力完全和 Spring Security整合。但是也有很多注意事項,下面就具體說下

 

一、 官方示例

首先,官網給出了簡單了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);
}

 

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章