• springboot和flowable modeler整合


    准备:项目使用的是springboot2.1.5版本,flowable6.4.0版本

    1. IDEA新建Spring Initializr项目,选择依赖,web和MySQL

    2. 修改pom.xml依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.5.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.sgcc.flowable</groupId>
        <artifactId>mpur-flowable-service</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
        <name>mpur-flowable-service</name>
        <description>mpur-flowable-service</description>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <mysql.version>5.1.38</mysql.version>
            <flowable.version>6.4.0</flowable.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.hibernate.validator</groupId>
                        <artifactId>hibernate-validator</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.21</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.21</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-spring-boot-starter</artifactId>
                <version>${flowable.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.54</version>
                <scope>compile</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.flowable/flowable-ui-modeler-logic -->
            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-ui-modeler-logic</artifactId>
                <version>6.4.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.flowable/flowable-ui-modeler-conf -->
            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-ui-modeler-conf</artifactId>
                <version>6.4.0</version>
            </dependency>
    
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

    3. 将下载的flowable6.4.0包中flowable-modeler.war解压,将flowable-modelerWEB-INFclasses目录下的static文件夹全部复制到项目中

    4. 修改RemoteAccountResource类,保持包目录不变。

    package org.flowable.ui.common.rest.idm.remote;
    
    import org.flowable.ui.common.model.UserRepresentation;
    import org.flowable.ui.common.security.DefaultPrivileges;
    import org.flowable.ui.common.service.exception.NotFoundException;
    import org.flowable.ui.common.service.idm.RemoteIdmService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @RestController
    @RequestMapping("/app")
    public class RemoteAccountResource {
    
        @Autowired
        private RemoteIdmService remoteIdmService;
    
        /**
         * GET /rest/account -> get the current user.
         */
        @RequestMapping(value = "/rest/account", method = RequestMethod.GET, produces = "application/json")
        public UserRepresentation getAccount() {
    //        UserRepresentation userRepresentation = null;
    //        String currentUserId = SecurityUtils.getCurrentUserId();
    //        if (currentUserId != null) {
    //            RemoteUser remoteUser = remoteIdmService.getUser(currentUserId);
    //            if (remoteUser != null) {
    //                userRepresentation = new UserRepresentation(remoteUser);
    //
    //                if (remoteUser.getGroups() != null && remoteUser.getGroups().size() > 0) {
    //                    List<GroupRepresentation> groups = new ArrayList<>();
    //                    for (RemoteGroup remoteGroup : remoteUser.getGroups()) {
    //                        groups.add(new GroupRepresentation(remoteGroup));
    //                    }
    //                    userRepresentation.setGroups(groups);
    //                }
    //
    //                if (remoteUser.getPrivileges() != null && remoteUser.getPrivileges().size() > 0) {
    //                    userRepresentation.setPrivileges(remoteUser.getPrivileges());
    //                }
    //
    //            }
    //        }
            UserRepresentation userRepresentation = new UserRepresentation();
            userRepresentation.setFirstName("admin");
            userRepresentation.setLastName("admin");
            userRepresentation.setFullName("admin");
            userRepresentation.setId("admin");
            List<String> pris = new ArrayList<>();
            pris.add(DefaultPrivileges.ACCESS_MODELER);
            pris.add(DefaultPrivileges.ACCESS_IDM);
            pris.add(DefaultPrivileges.ACCESS_ADMIN);
            pris.add(DefaultPrivileges.ACCESS_TASK);
            pris.add(DefaultPrivileges.ACCESS_REST_API);
            userRepresentation.setPrivileges(pris);
    
            if (userRepresentation != null) {
                return userRepresentation;
            } else {
                throw new NotFoundException();
            }
        }
    
    }

    5. 修改SecurityUtils类,保证包目录不变。

    /* Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package org.flowable.ui.common.security;
    
    import org.flowable.idm.api.User;
    import org.flowable.ui.common.model.RemoteUser;
    import org.flowable.ui.common.security.DefaultPrivileges;
    import org.flowable.ui.common.security.FlowableAppUser;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.context.SecurityContext;
    import org.springframework.security.core.context.SecurityContextHolder;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Utility class for Spring Security.
     */
    public class SecurityUtils {
    
        private static User assumeUser;
    
        private SecurityUtils() {
        }
    
        /**
         * Get the login of the current user.
         */
        public static String getCurrentUserId() {
            User user = getCurrentUserObject();
            if (user != null) {
                return user.getId();
            }
            return null;
        }
    
        /**
         * @return the {@link User} object associated with the current logged in user.
         */
        public static User getCurrentUserObject() {
            if (assumeUser != null) {
                return assumeUser;
            }
    
    //        User user = null;
    //        FlowableAppUser appUser = getCurrentFlowableAppUser();
    //        if (appUser != null) {
    //            user = appUser.getUserObject();
    //        }
    
            RemoteUser user = new RemoteUser();
    //        FlowableAppUser appUser = getCurrentFlowableAppUser();
    //        if (appUser != null) {
    //            user = appUser.getUserObject();
    //        }
            user.setId("admin");
            user.setDisplayName("admin");
            user.setFirstName("admin");
            user.setLastName("admin");
            user.setEmail("admin@admin.com");
            user.setPassword("test");
            List<String> pris = new ArrayList<>();
            pris.add(DefaultPrivileges.ACCESS_MODELER);
            pris.add(DefaultPrivileges.ACCESS_IDM);
            pris.add(DefaultPrivileges.ACCESS_ADMIN);
            pris.add(DefaultPrivileges.ACCESS_TASK);
            pris.add(DefaultPrivileges.ACCESS_REST_API);
            user.setPrivileges(pris);
            return user;
        }
    
        public static FlowableAppUser getCurrentFlowableAppUser() {
            FlowableAppUser user = null;
            SecurityContext securityContext = SecurityContextHolder.getContext();
            if (securityContext != null && securityContext.getAuthentication() != null) {
                Object principal = securityContext.getAuthentication().getPrincipal();
                if (principal instanceof FlowableAppUser) {
                    user = (FlowableAppUser) principal;
                }
            }
            return user;
        }
    
        public static boolean currentUserHasCapability(String capability) {
            FlowableAppUser user = getCurrentFlowableAppUser();
            for (GrantedAuthority grantedAuthority : user.getAuthorities()) {
                if (capability.equals(grantedAuthority.getAuthority())) {
                    return true;
                }
            }
            return false;
        }
    
        public static void assumeUser(User user) {
            assumeUser = user;
        }
    
        public static void clearAssumeUser() {
            assumeUser = null;
        }
    
    }

    6.  修改SecurityConfiguration类,保证包目录不变。

    /* Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package org.flowable.ui.modeler.conf;
    
    import org.flowable.ui.common.properties.FlowableRestAppProperties;
    import org.flowable.ui.common.security.ActuatorRequestMatcher;
    import org.flowable.ui.common.security.ClearFlowableCookieLogoutHandler;
    import org.flowable.ui.common.security.DefaultPrivileges;
    import org.flowable.ui.modeler.properties.FlowableModelerAppProperties;
    import org.flowable.ui.modeler.security.AjaxLogoutSuccessHandler;
    import org.flowable.ui.modeler.security.RemoteIdmAuthenticationProvider;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
    import org.springframework.boot.actuate.health.HealthEndpoint;
    import org.springframework.boot.actuate.info.InfoEndpoint;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter;
    
    /**
     * Based on http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#multiple-httpsecurity
     *
     * @author Joram Barrez
     * @author Tijs Rademakers
     * @author Filip Hrisafov
     */
    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(org.flowable.ui.modeler.conf.SecurityConfiguration.class);
    
        public static final String REST_ENDPOINTS_PREFIX = "/app/rest";
    
        @Autowired
        protected RemoteIdmAuthenticationProvider authenticationProvider;
    
    //    @Bean
    //    public FlowableCookieFilterRegistrationBean flowableCookieFilterRegistrationBean(RemoteIdmService remoteIdmService, FlowableCommonAppProperties properties) {
    //        FlowableCookieFilterRegistrationBean filter = new FlowableCookieFilterRegistrationBean(remoteIdmService, properties);
    //        filter.addUrlPatterns("/app/*");
    //        filter.setRequiredPrivileges(Collections.singletonList(DefaultPrivileges.ACCESS_MODELER));
    //        return filter;
    //    }
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) {
    
            // Default auth (database backed)
            try {
                auth.authenticationProvider(authenticationProvider);
            } catch (Exception e) {
                LOGGER.error("Could not configure authentication mechanism:", e);
            }
        }
    
        @Configuration
        @Order(10)
        public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    
    //        @Autowired
    //        protected FlowableCookieFilterRegistrationBean flowableCookieFilterRegistrationBean;
    
            @Autowired
            protected AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler;
    
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                        .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                        .and()
    //                    .addFilterBefore(flowableCookieFilterRegistrationBean.getFilter(), UsernamePasswordAuthenticationFilter.class)
                        .logout()
                        .logoutUrl("/app/logout")
                        .logoutSuccessHandler(ajaxLogoutSuccessHandler)
                        .addLogoutHandler(new ClearFlowableCookieLogoutHandler())
                        .and()
                        .csrf()
                        .disable() // Disabled, cause enabling it will cause sessions
                        .headers()
                        .frameOptions()
                        .sameOrigin()
                        .addHeaderWriter(new XXssProtectionHeaderWriter())
                        .and()
                        .authorizeRequests()
    //                    .antMatchers(REST_ENDPOINTS_PREFIX + "/**").hasAuthority(DefaultPrivileges.ACCESS_MODELER);
                        .antMatchers(REST_ENDPOINTS_PREFIX + "/**").permitAll();
            }
        }
    
        //
        // BASIC AUTH
        //
    
        @Configuration
        @Order(1)
        public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
    
            protected final FlowableRestAppProperties restAppProperties;
            protected final FlowableModelerAppProperties modelerAppProperties;
    
            public ApiWebSecurityConfigurationAdapter(FlowableRestAppProperties restAppProperties,
                                                      FlowableModelerAppProperties modelerAppProperties) {
                this.restAppProperties = restAppProperties;
                this.modelerAppProperties = modelerAppProperties;
            }
    
            protected void configure(HttpSecurity http) throws Exception {
    
                http
                        .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                        .and()
                        .csrf()
                        .disable();
    
                http.antMatcher("/api/**").authorizeRequests().antMatchers("/api/**").permitAll();
    
    //            if (modelerAppProperties.isRestEnabled()) {
    //
    //                if (restAppProperties.isVerifyRestApiPrivilege()) {
    //                    http.antMatcher("/api/**").authorizeRequests().antMatchers("/api/**").hasAuthority(DefaultPrivileges.ACCESS_REST_API).and().httpBasic();
    //                } else {
    //                    http.antMatcher("/api/**").authorizeRequests().antMatchers("/api/**").authenticated().and().httpBasic();
    //
    //                }
    //
    //            } else {
    //                http.antMatcher("/api/**").authorizeRequests().antMatchers("/api/**").denyAll();
    //
    //            }
    
            }
        }
    
        //
        // Actuator
        //
    
        @ConditionalOnClass(EndpointRequest.class)
        @Configuration
        @Order(5) // Actuator configuration should kick in before the Form Login there should always be http basic for the endpoints
        public static class ActuatorWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
    
            protected void configure(HttpSecurity http) throws Exception {
    
                http
                        .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                        .and()
                        .csrf()
                        .disable();
    
                http
                        .requestMatcher(new ActuatorRequestMatcher())
                        .authorizeRequests()
                        .requestMatchers(EndpointRequest.to(InfoEndpoint.class, HealthEndpoint.class)).authenticated()
                        .requestMatchers(EndpointRequest.toAnyEndpoint()).hasAnyAuthority(DefaultPrivileges.ACCESS_ADMIN)
                        .and().httpBasic();
            }
        }
    }

    7. 配置日志信息,flowable使用的是slf4j日志,新建文件log4j.properties,内容如下:

    log4j.rootLogger=DEBUG, CA
    
    log4j.appender.CA=org.apache.log4j.ConsoleAppender
    log4j.appender.CA.layout=org.apache.log4j.PatternLayout
    log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n

    8. 项目配置,新建application.yml,文件内容:

    ###################  端口配置 ###################
    server:
      port: 8989
    
    
    ###################  spring配置  ###################
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/flowable?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&nullCatalogMeansCurrent=true
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver
    
    
    flowable:
        common:
          app:
            idm-url: http://localhost:8989/flowable-idm
            idm-admin:
              user: admin
              password: test
    
        async-executor-activate: false #关闭定时任务JOB
        database-schema-update: false

    9. 启动项目,访问http://localhost:8989/即可

  • 相关阅读:
    内存之RAM、SRAM、DRAM、ROM、FLASH、SDRAM、DDR*
    音频接口之AUX、TRS、RCA、SLR、AES/EBU、S/PDIF
    视频接口之AV、S端子、VGA、DVI、HDMI、DP
    选购硬盘HDD、SSD、SSHD、IDE、SATA、SCSI、SAS、PCIe、M.2、USB
    浅析C#中的“==”和Equals
    编写更好的C#代码
    C# 文件下载四方法
    Linq之Lambda表达式初步认识
    .NET逻辑分层架构总结
    理解 .NET 2015
  • 原文地址:https://www.cnblogs.com/yangjiming/p/10944120.html
Copyright © 2020-2023  润新知