| @@ -50,6 +50,12 @@ | |||
| <groupId>mysql</groupId> | |||
| <artifactId>mysql-connector-java</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.projectlombok</groupId> | |||
| <artifactId>lombok</artifactId> | |||
| <optional>true</optional> | |||
| </dependency> | |||
| </dependencies> | |||
| <build> | |||
| @@ -0,0 +1,64 @@ | |||
| package com.xkcoding.activiti.config; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | |||
| import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | |||
| import org.springframework.security.core.authority.SimpleGrantedAuthority; | |||
| import org.springframework.security.core.userdetails.User; | |||
| import org.springframework.security.core.userdetails.UserDetailsService; | |||
| import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | |||
| import org.springframework.security.crypto.password.PasswordEncoder; | |||
| import org.springframework.security.provisioning.InMemoryUserDetailsManager; | |||
| import java.util.Arrays; | |||
| import java.util.List; | |||
| import java.util.stream.Collectors; | |||
| /** | |||
| * <p> | |||
| * 安全配置类 | |||
| * </p> | |||
| * | |||
| * @package: com.xkcoding.activiti.config | |||
| * @description: 安全配置类 | |||
| * @author: yangkai.shen | |||
| * @date: Created in 2019-07-01 18:40 | |||
| * @copyright: Copyright (c) 2019 | |||
| * @version: V1.0 | |||
| * @modified: yangkai.shen | |||
| */ | |||
| @Slf4j | |||
| @Configuration | |||
| public class SecurityConfiguration extends WebSecurityConfigurerAdapter { | |||
| @Override | |||
| protected void configure(AuthenticationManagerBuilder auth) throws Exception { | |||
| auth.userDetailsService(userDetailsService()); | |||
| } | |||
| @Bean | |||
| protected UserDetailsService myUserDetailsService() { | |||
| InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(); | |||
| String[][] usersGroupsAndRoles = {{"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"}, {"ryandawsonuk", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"}, {"erdemedeiros", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"}, {"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"}, {"admin", "password", "ROLE_ACTIVITI_ADMIN"}}; | |||
| for (String[] user : usersGroupsAndRoles) { | |||
| List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length)); | |||
| log.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]"); | |||
| inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]), authoritiesStrings | |||
| .stream() | |||
| .map(SimpleGrantedAuthority::new) | |||
| .collect(Collectors.toList()))); | |||
| } | |||
| return inMemoryUserDetailsManager; | |||
| } | |||
| @Bean | |||
| public PasswordEncoder passwordEncoder() { | |||
| return new BCryptPasswordEncoder(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,79 @@ | |||
| package com.xkcoding.activiti.util; | |||
| import lombok.RequiredArgsConstructor; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.security.core.Authentication; | |||
| import org.springframework.security.core.GrantedAuthority; | |||
| import org.springframework.security.core.context.SecurityContextHolder; | |||
| import org.springframework.security.core.context.SecurityContextImpl; | |||
| import org.springframework.security.core.userdetails.UserDetails; | |||
| import org.springframework.security.core.userdetails.UserDetailsService; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.Collection; | |||
| /** | |||
| * <p> | |||
| * 认证工具 | |||
| * </p> | |||
| * | |||
| * @package: com.xkcoding.activiti.util | |||
| * @description: 认证工具 | |||
| * @author: yangkai.shen | |||
| * @date: Created in 2019-07-01 18:38 | |||
| * @copyright: Copyright (c) 2019 | |||
| * @version: V1.0 | |||
| * @modified: yangkai.shen | |||
| */ | |||
| @Component | |||
| @RequiredArgsConstructor(onConstructor_ = @Autowired) | |||
| public class SecurityUtil { | |||
| private final 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); | |||
| } | |||
| } | |||
| @@ -0,0 +1,78 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | |||
| <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:yaoqiang="http://bpmn.sourceforge.net" exporter="Yaoqiang BPMN Editor" exporterVersion="5.3" expressionLanguage="http://www.w3.org/1999/XPath" id="m1544167269809" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL http://bpmn.sourceforge.net/schemas/BPMN20.xsd"> | |||
| <process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"> | |||
| <extensionElements> | |||
| <yaoqiang:description/> | |||
| <yaoqiang:pageFormat height="841.8897637795276" imageableHeight="831.8897637795276" imageableWidth="588.1102362204724" imageableX="5.0" imageableY="5.0" orientation="0" width="598.1102362204724"/> | |||
| <yaoqiang:page background="#FFFFFF" horizontalCount="1" verticalCount="1"/> | |||
| </extensionElements> | |||
| <startEvent id="_2" isInterrupting="true" name="StartEvent" parallelMultiple="false"> | |||
| <outgoing>_6</outgoing> | |||
| <outputSet/> | |||
| </startEvent> | |||
| <userTask activiti:candidateGroups="activitiTeam" activiti:exclusive="true" completionQuantity="1" id="_3" implementation="##unspecified" isForCompensation="false" name="first" startQuantity="1"> | |||
| <incoming>_6</incoming> | |||
| <outgoing>_7</outgoing> | |||
| </userTask> | |||
| <userTask activiti:candidateGroups="activitiTeam" activiti:exclusive="true" completionQuantity="1" id="_4" implementation="##unspecified" isForCompensation="false" name="second" startQuantity="1"> | |||
| <incoming>_7</incoming> | |||
| <outgoing>_8</outgoing> | |||
| </userTask> | |||
| <endEvent id="_5" name="EndEvent"> | |||
| <incoming>_8</incoming> | |||
| <inputSet/> | |||
| </endEvent> | |||
| <sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/> | |||
| <sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/> | |||
| <sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/> | |||
| </process> | |||
| <bpmndi:BPMNDiagram id="Yaoqiang_Diagram-myProcess_1" name="New Diagram" resolution="96.0"> | |||
| <bpmndi:BPMNPlane bpmnElement="myProcess_1"> | |||
| <bpmndi:BPMNShape bpmnElement="_2" id="Yaoqiang-_2"> | |||
| <omgdc:Bounds height="32.0" width="32.0" x="65.0" y="80.0"/> | |||
| <bpmndi:BPMNLabel> | |||
| <omgdc:Bounds height="18.96" width="60.0" x="51.0" y="120.52"/> | |||
| </bpmndi:BPMNLabel> | |||
| </bpmndi:BPMNShape> | |||
| <bpmndi:BPMNShape bpmnElement="_3" id="Yaoqiang-_3"> | |||
| <omgdc:Bounds height="55.0" width="85.0" x="170.0" y="115.0"/> | |||
| <bpmndi:BPMNLabel> | |||
| <omgdc:Bounds height="18.96" width="28.0" x="198.5" y="135.02"/> | |||
| </bpmndi:BPMNLabel> | |||
| </bpmndi:BPMNShape> | |||
| <bpmndi:BPMNShape bpmnElement="_4" id="Yaoqiang-_4"> | |||
| <omgdc:Bounds height="55.0" width="85.0" x="310.0" y="155.0"/> | |||
| <bpmndi:BPMNLabel> | |||
| <omgdc:Bounds height="18.96" width="45.0" x="330.0" y="175.02"/> | |||
| </bpmndi:BPMNLabel> | |||
| </bpmndi:BPMNShape> | |||
| <bpmndi:BPMNShape bpmnElement="_5" id="Yaoqiang-_5"> | |||
| <omgdc:Bounds height="32.0" width="32.0" x="505.0" y="220.0"/> | |||
| <bpmndi:BPMNLabel> | |||
| <omgdc:Bounds height="18.96" width="55.0" x="493.5" y="260.52"/> | |||
| </bpmndi:BPMNLabel> | |||
| </bpmndi:BPMNShape> | |||
| <bpmndi:BPMNEdge bpmnElement="_8" id="Yaoqiang-_8"> | |||
| <omgdi:waypoint x="395.0" y="182.5"/> | |||
| <omgdi:waypoint x="505.0" y="236.0"/> | |||
| <bpmndi:BPMNLabel> | |||
| <omgdc:Bounds height="18.96" width="6.0" x="447.0" y="199.77"/> | |||
| </bpmndi:BPMNLabel> | |||
| </bpmndi:BPMNEdge> | |||
| <bpmndi:BPMNEdge bpmnElement="_7" id="Yaoqiang-_7"> | |||
| <omgdi:waypoint x="255.0" y="142.5"/> | |||
| <omgdi:waypoint x="310.0" y="182.5"/> | |||
| <bpmndi:BPMNLabel> | |||
| <omgdc:Bounds height="18.96" width="6.0" x="279.5" y="153.02"/> | |||
| </bpmndi:BPMNLabel> | |||
| </bpmndi:BPMNEdge> | |||
| <bpmndi:BPMNEdge bpmnElement="_6" id="Yaoqiang-_6"> | |||
| <omgdi:waypoint x="97.0" y="96.0"/> | |||
| <omgdi:waypoint x="170.0" y="142.5"/> | |||
| <bpmndi:BPMNLabel> | |||
| <omgdc:Bounds height="18.96" width="6.0" x="130.5" y="109.77"/> | |||
| </bpmndi:BPMNLabel> | |||
| </bpmndi:BPMNEdge> | |||
| </bpmndi:BPMNPlane> | |||
| </bpmndi:BPMNDiagram> | |||
| </definitions> | |||
| @@ -1,7 +1,13 @@ | |||
| package com.xkcoding.activiti; | |||
| import com.xkcoding.activiti.util.SecurityUtil; | |||
| import org.activiti.api.process.model.ProcessDefinition; | |||
| import org.activiti.api.process.runtime.ProcessRuntime; | |||
| import org.activiti.api.runtime.shared.query.Page; | |||
| import org.activiti.api.runtime.shared.query.Pageable; | |||
| import org.junit.Test; | |||
| import org.junit.runner.RunWith; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.boot.test.context.SpringBootTest; | |||
| import org.springframework.test.context.junit4.SpringRunner; | |||
| @@ -9,8 +15,16 @@ import org.springframework.test.context.junit4.SpringRunner; | |||
| @SpringBootTest | |||
| public class SpringBootDemoActivitiApplicationTests { | |||
| @Autowired | |||
| private ProcessRuntime processRuntime; | |||
| @Autowired | |||
| private SecurityUtil securityUtil; | |||
| @Test | |||
| public void contextLoads() { | |||
| securityUtil.logInAs("salaboy"); | |||
| Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10)); | |||
| processDefinitionPage.getContent().forEach(System.out::println); | |||
| } | |||
| } | |||