@@ -50,6 +50,12 @@ | |||||
<groupId>mysql</groupId> | <groupId>mysql</groupId> | ||||
<artifactId>mysql-connector-java</artifactId> | <artifactId>mysql-connector-java</artifactId> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>org.projectlombok</groupId> | |||||
<artifactId>lombok</artifactId> | |||||
<optional>true</optional> | |||||
</dependency> | |||||
</dependencies> | </dependencies> | ||||
<build> | <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; | 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.Test; | ||||
import org.junit.runner.RunWith; | import org.junit.runner.RunWith; | ||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.boot.test.context.SpringBootTest; | import org.springframework.boot.test.context.SpringBootTest; | ||||
import org.springframework.test.context.junit4.SpringRunner; | import org.springframework.test.context.junit4.SpringRunner; | ||||
@@ -9,8 +15,16 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
@SpringBootTest | @SpringBootTest | ||||
public class SpringBootDemoActivitiApplicationTests { | public class SpringBootDemoActivitiApplicationTests { | ||||
@Autowired | |||||
private ProcessRuntime processRuntime; | |||||
@Autowired | |||||
private SecurityUtil securityUtil; | |||||
@Test | @Test | ||||
public void contextLoads() { | public void contextLoads() { | ||||
securityUtil.logInAs("salaboy"); | |||||
Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10)); | |||||
processDefinitionPage.getContent().forEach(System.out::println); | |||||
} | } | ||||
} | } | ||||