栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

snowy小诺与camunda7.15版本集成

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

snowy小诺与camunda7.15版本集成

目录

snowy开源版本拉取:

springboot与camunda版本对比:

camunda7.15版本相关依赖,引入snowy-main中的pom文件:

snowy父pom将spring-boot-starter-parent版本进行(选择性)修改为2.4.3

yaml camunda的账户配置(选择性)

SnowyApplication启动类进行修改,添加camunda注解@EnableProcessApplication

将camunda接口相关权限放开SpringSecurityConstant:

启动后端,访问地址:http://localhost:82/camunda/app/welcome/default/#!/login

接管小诺放行的请求,开启camunda的请求拦截(鉴权):

sso自动登录

自动登录测试

对camunda的鉴权进行自定义(选择性使用)

放行camunda请求的,请求头校验

camunda鉴权开启效果

 camunda web页面开启汉化

嵌入式表单位置:/resources/static/forms


  • snowy开源版本拉取:

Snowy: Snowy基于SpringBoot+AntDesignVue的前后分离全新RBAC权限管理系统,适配国产数据库(金仓、达梦)、主流数据库Mysql、Oracle、Mssql、Postgresql,小诺一致追求简洁干净,一套代码搞定!支持国产中间件部署、麒麟操作系统、Windows、Linux部署使用,另外支持saas多租户、flowable工作流、多数据源、支付模块等,更多插件正在扩展中。https://gitee.com/xiaonuobase/snowy

  • springboot与camunda版本对比:

Spring Boot Version Compatibility | docs.camunda.orgdocumentation of the Camunda Platformhttps://docs.camunda.org/manual/7.15/user-guide/spring-boot-integration/version-compatibility/

  • camunda7.15版本相关依赖,引入snowy-main中的pom文件:

        
        
            org.camunda.bpm.springboot
            camunda-bpm-spring-boot-starter-rest
            7.15.0
        

        
            org.camunda.bpm.springboot
            camunda-bpm-spring-boot-starter-webapp
            7.15.0
        

        
            org.camunda.bpm
            camunda-engine-plugin-spin
            7.15.0
        

        
            org.camunda.spin
            camunda-spin-dataformat-all
            1.11.0
        
        
  • snowy父pom将spring-boot-starter-parent版本进行(选择性)修改为2.4.3

    
        org.springframework.boot
        spring-boot-starter-parent

        2.4.3
    
  • yaml camunda的账户配置(选择性)

如果不进行配置,那么在你登录的camunda官方提供的web页面时,camunda也会要求你初始化一个超级管理员的账户

camunda.bpm.admin-user:
  id: admin
  password: admin
  • SnowyApplication启动类进行修改,添加camunda注解@EnableProcessApplication

// 防止过滤器创建报空指针异常(2-1)(springSecurityConstant需要放开路径:"/camunda/api/engine")
@EnableProcessApplication
@SpringBootApplication
public class SnowyApplication {……}
  • 将camunda接口相关权限放开SpringSecurityConstant:

public interface SpringSecurityConstant {

    
    String[] NONE_SECURITY_URL_PATTERNS = {

            ……

            // modeler 流程部署接口
            "/engine-rest
@Configuration
public class CamundaSecurityFilter {
    @Bean
    public FilterRegistrationBean processEngineAuthenticationFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean<>(new ProcessEngineAuthenticationFilter());
//        registration.setName("camunda-auth");
//        registration.setFilter(new ProcessEngineAuthenticationFilter());
        // camunda官方提供的鉴权(推荐)
        registration.addInitParameter("authentication-provider",
                "org.camunda.bpm.engine.rest.security.auth.impl.HttpBasicAuthenticationProvider");
        // 根据camunda官方提供的鉴权进行改写(如果自己的系统不需要访问官方的接口,那么推荐使用camunda的鉴权)
//        processEngineAuthenticationFilterRegistrationBean.addInitParameter("authentication-provider",
//                "vip.xiaonuo.camunda.common.auth.provider.CamundaAuthenticationProvider");
        registration.addUrlPatterns("/engine-rest
@Configuration
public class CamundaSecurityConfig {
    // ContainerbasedAuthenticationFilter、ContainerbasedAuthenticationProvider
    @Bean
    public FilterRegistrationBean containerbasedAuthenticationFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean<>();
        registration.setName("camunda-auth");
        registration.setFilter(new AutoLoginAuthenticationFilter());
        registration.addUrlPatterns("/camunda/app
public class AutoLoginAuthenticationFilter implements Filter {

    private static final String[] APPS = new String[] { "cockpit", "tasklist", "admin", "welcome" };

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest req = (HttpServletRequest) request;

        // get authentication from session
        Authentications authentications = Authentications.getFromSession(req.getSession());

        // This function is added to the normal AuthenticationFilter
        setAutoLoginAuthentication(request, authentications);

        // set current authentication to the one restored from session (maybe
        // auto login was added)
        Authentications.setCurrent(authentications);

        try {

            SecurityActions.runWithAuthentications(new SecurityAction() {
                @Override
                public Void execute() {
                    try {
                        chain.doFilter(request, response);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    return null;
                }
            }, authentications);
        } finally {
            Authentications.clearCurrent();
            // store updated authentication object in session for next request
            Authentications.updateSession(req.getSession(), authentications);
        }
    }

    
    protected void setAutoLoginAuthentication(final ServletRequest request, Authentications authentications) {
        final HttpServletRequest req = (HttpServletRequest) request;
        final ProcessEngine engine = getEngine();

        // Get the username from the user in SSO
        String username = retrieveUsername(req);

        // if not set - no auto login
        if (username == null) {
            return;
        }

        // if already in the list of logged in users - nothing to do
        Authentication authentication = authentications.getAuthenticationForProcessEngine(engine.getName());
        if (authentication != null && authentication.getName() == username) {
            return;
        }

        AuthorizationService authorizationService = engine.getAuthorizationService();

        // query group information
        List groupIds = getGroupsOfUser(engine, username);
        List tenantIds = getTenantsOfUser(engine, username);

        // check user's app authorizations by iterating of list of apps and ask
        // if permitted
        HashSet authorizedApps = new HashSet();
        authorizedApps.add("admin");
        if (engine.getProcessEngineConfiguration().isAuthorizationEnabled()) {
            for (String application : APPS) {
                if (authorizationService.isUserAuthorized(username, groupIds, ACCESS, APPLICATION, application)) {
                    authorizedApps.add(application);
                }
            }
        } else {
            Collections.addAll(authorizedApps, APPS);
        }

        // create new authentication object to store authentication
        UserAuthentication newAuthentication = new UserAuthentication(username, engine.getName());
        newAuthentication.setGroupIds(groupIds);
        newAuthentication.setTenantIds(tenantIds);
        newAuthentication.setAuthorizedApps(authorizedApps);

        // and add the new logged in user
        authentications.addAuthentication(newAuthentication);
    }

    
    protected String retrieveUsername(final HttpServletRequest req) {
        // Simply read it from a URL parameter in this case
        return req.getParameter("auto-login-username");
    }

    
    protected List getGroupsOfUser(ProcessEngine engine, String userId) {
        List groups = engine.getIdentityService().createGroupQuery().groupMember(userId).list();

        List groupIds = new ArrayList();
        for (Group group : groups) {
            groupIds.add(group.getId());
        }
        return groupIds;
    }

    protected List getTenantsOfUser(ProcessEngine engine, String userId) {
        List tenants = engine.getIdentityService().createTenantQuery().userMember(userId).includingGroupsOfUser(true).list();

        List tenantIds = new ArrayList();
        for (Tenant tenant : tenants) {
            tenantIds.add(tenant.getId());
        }
        return tenantIds;
    }

    private ProcessEngine getEngine() {
        // TODO: only works in single engine environment!
        return BpmPlatform.getDefaultProcessEngine();
    }

}
  • 自动登录测试

http://localhost:82/camunda/app/welcome/?auto-login-username=admin

  • 对camunda的鉴权进行自定义(选择性使用)

如果自己的系统要直接访问camunda官方提供的接口,那么就需要对camunda的鉴权进行自定义,可参考以下内容:

package vip.xiaonuo.camunda.common.auth.provider;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.identity.User;
import org.camunda.bpm.engine.impl.digest._apacheCommonsCodec.base64;
import org.camunda.bpm.engine.rest.security.auth.AuthenticationProvider;
import org.camunda.bpm.engine.rest.security.auth.AuthenticationResult;
import org.springframework.util.StringUtils;
import vip.xiaonuo.core.context.login.LoginContextHolder;
import vip.xiaonuo.core.pojo.login.SysLoginUser;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.HttpHeaders;



public class CamundaAuthenticationProvider implements AuthenticationProvider {
    protected static final String BASIC_AUTH_HEADER_PREFIX = "Basic ";
    protected static final String TOKEN_TYPE_BEARER = "Bearer";
    @Override
    public AuthenticationResult extractAuthenticatedUser(HttpServletRequest request, ProcessEngine engine) {
        String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (authorizationHeader != null) {
            if(authorizationHeader.startsWith(BASIC_AUTH_HEADER_PREFIX)){
                String encodedCredentials = authorizationHeader.substring(BASIC_AUTH_HEADER_PREFIX.length());
                String decodedCredentials = new String(base64.decodebase64(encodedCredentials));
                int firstColonIndex = decodedCredentials.indexOf(":");
                if (firstColonIndex != -1) {
                    String userName = decodedCredentials.substring(0, firstcolonIndex);
                    String password = decodedCredentials.substring(firstColonIndex + 1);
                    if (isAuthenticated(engine, userName, password)) {
                        return AuthenticationResult.successful(userName);
                    }
                }
            }
            if(authorizationHeader.startsWith(TOKEN_TYPE_BEARER)){
                SysLoginUser sysLoginUser = LoginContextHolder.me().getSysLoginUser();
                // AuthService authService = SpringUtil.getBean(AuthService.class);
                User user = engine.getIdentityService().createUserQuery().userId(sysLoginUser.getAccount()).singleResult();
                if(!StringUtils.isEmpty(user)){
                    return AuthenticationResult.successful(user.getId());
                }
            }
        }
        return AuthenticationResult.unsuccessful();
    }
    protected boolean isAuthenticated(ProcessEngine engine, String userName, String password) {
        return engine.getIdentityService().checkPassword(userName, password);
    }
    @Override
    public void augmentResponseByAuthenticationChallenge(
            HttpServletResponse response, ProcessEngine engine) {
        response.setHeader(HttpHeaders.WWW_AUTHENTICATE, BASIC_AUTH_HEADER_PREFIX + "realm="" + engine.getName() + """);
    }

}
  • 放行camunda请求的,请求头校验

camunda开启鉴权后,官方的web请求会在请求头中携带authorization且以Basic作为开头,目前很多国内的系统,在鉴权的过程中,大部分都是先判断请求头中的是否含有authorization,如果有那么就判断是头是以Bearer作为开头,如果不是的话,那么就认为该请求头不符合规范,返回给前端;所以要想camunda的接口能够正常使用,那么就需要对框架中的这部分逻辑进行改进,以小诺框架为例,可参考以下内容:

注意这是一个坑:camunda的流程设计器,在鉴权未开启时,请求头中的authorization也会携带内容传递给后端,此时携带的内容为“undefined”字符串,针对这种情况,后端在针对这种情况时,也要进行放行

    @Override
    public String getTokenFromRequest(HttpServletRequest request) {
        String authToken = request.getHeader(CommonConstant.AUTHORIZATION);
        // 放行camunda以Basic开头的请求头
        if (ObjectUtil.isEmpty(authToken) || CommonConstant.UNDEFINED.equals(authToken)||authToken.startsWith(CommonConstant.TOKEN_TYPE_BASIC)) {
            return null;
        } else {
            //token不是以Bearer打头,则响应回格式不正确
            if (!authToken.startsWith(CommonConstant.TOKEN_TYPE_BEARER)) {
                throw new AuthException(AuthExceptionEnum.NOT_VALID_TOKEN_TYPE);
            }
            try {
                authToken = authToken.substring(CommonConstant.TOKEN_TYPE_BEARER.length() + 1);
            } catch (StringIndexOutOfBoundsException e) {
                throw new AuthException(AuthExceptionEnum.NOT_VALID_TOKEN_TYPE);
            }
        }

        return authToken;
    }
  • camunda鉴权开启效果

  • 流程设计器发生的变化:

Download The Camunda BPMN / DMN Process Modeler | CamundaA free and easy-to-use desktop app for editing BPMN Process Diagrams, DMN Decision Tables, and Forms. Camunda Modeler supports BPMN 2.0 and DMN 1.3.https://camunda.com/download/modeler/部署请求地址:http://localhost:82/engine-rest

  • camunda官方web发生的变化:

 此时再访问后端的接口在未登录的情况下访问:http://localhost:82/camunda/api/engine/engine/default/task/43483a51-2524-11ec-9fe5-861b7790c7c0

会出现如下效果:

  •  camunda web页面开启汉化

camunda7.15版本汉化_camunda汉化-企业管理文档类资源-CSDN下载camunda7.15版本汉化camunda汉化更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/weixin_44213308/21481004目录结构如下:

除了cockpit,admin和task,都汉化过了,注意:汉化区分版本7.14版本的汉化过程与7.15版本是有区别的,这是7.15版本的汉化过程。

效果如下:

  • 嵌入式表单位置:/resources/static/forms

具体使用方式,参考:

的博客-CSDN博客">camunda集成系列教程3-嵌入式表单_<每天一点>的博客-CSDN博客https://docs.camunda.org/manual/latest/user-guide/task-forms/#camunda-forms首先,camunda平台的表单分为三种:1、嵌入式任务表单允许您将自定义 HTML 和 Javascript 表单嵌入到任务列表中。2、Camunda Forms在 Camunda Modeler 中提供表单的可视化编辑,可用于不太复杂的表单。3、外部任务表单可用于链接到自定义应用程序。表单不会嵌入到任务列表中。首先在了解表单之前,我们先了https://blog.csdn.net/weixin_44213308/article/details/119715559

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/301060.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号