1. Обзор
Activity-это система BPM (управления бизнес-процессами) с открытым исходным кодом. Для ознакомления ознакомьтесь с нашим Руководством по работе с Java .
Как Activity, так и Spring framework обеспечивают собственное управление идентификацией. Однако в приложении, которое объединяет оба проекта, мы можем захотеть объединить их в единый процесс управления пользователями.
Ниже мы рассмотрим две возможности для достижения этой цели: одна заключается в предоставлении службы пользователей с поддержкой активности для Spring Security, а другая-в подключении источника пользователей Spring Security к управлению идентификацией Activiti.
2. Зависимости Maven
Чтобы настроить активность в проекте Spring Boot, ознакомьтесь с нашей предыдущей статьей . В дополнение к activiti-spring-boot-starter-basic, нам также понадобится activiti-spring-boot-starter-security зависимость:
org.activiti activiti-spring-boot-starter-security 6.0.0
3. Управление Идентификацией С Помощью Активности
Для этого сценария стартеры действий предоставляют класс автоматической конфигурации Spring Boot, который обеспечивает защиту всех конечных точек REST с помощью HTTP Basic аутентификации.
Автоматическая настройка также создает UserDetailsService фасоль класса Служба идентификации UserDetailsService.
Класс реализует интерфейс Spring UserDetailsService и переопределяет метод loadUserByUsername () . Этот метод извлекает объект Activity User с заданным id и использует его для создания объекта Spring UserDetails .
Кроме того, объект Activity Group соответствует роли пользователя Spring.
Это означает, что при входе в приложение Spring Security мы будем использовать учетные данные активности.
3.1. Настройка Активности Пользователей
Во-первых, давайте создадим пользователя в InitializingBean , определенном в основном @SpringBootApplication классе, используя IdentityService:
@Bean
InitializingBean usersAndGroupsInitializer(IdentityService identityService) {
return new InitializingBean() {
public void afterPropertiesSet() throws Exception {
User user = identityService.newUser("activiti_user");
user.setPassword("pass");
identityService.saveUser(user);
Group group = identityService.newGroup("user");
group.setName("ROLE_USER");
group.setType("USER");
identityService.saveGroup(group);
identityService.createMembership(user.getId(), group.getId());
}
};
}Вы заметите, что поскольку это будет использоваться Spring Security, Группа объект имя должно иметь форму “ROLE_X” .
3.2. Конфигурация безопасности Spring
Если мы хотим использовать другую конфигурацию безопасности вместо базовой аутентификации HTTP, сначала мы должны исключить автоматическую настройку:
@SpringBootApplication(
exclude = org.activiti.spring.boot.SecurityAutoConfiguration.class)
public class ActivitiSpringSecurityApplication {
// ...
}Затем мы можем предоставить наш собственный класс конфигурации безопасности Spring, который использует Identity Service UserDetailsService для извлечения пользователей из источника данных Activiti:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private IdentityService identityService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService());
}
@Bean
public UserDetailsService userDetailsService() {
return new IdentityServiceUserDetailsService(
this.identityService);
}
// spring security configuration
}4. Управление Идентификацией С Помощью Spring Security
Если у нас уже настроено управление пользователями с помощью Spring Security, и мы хотим добавить активность в наше приложение, нам необходимо настроить управление идентификацией.
Для этой цели мы должны расширить два основных класса: User EntityManagerImpl и Group EntityManagerImpl , которые обрабатывают пользователей и группы.
Давайте рассмотрим каждый из них более подробно.
4.1. Расширение пользовательского EntityManagerImpl
Давайте создадим наш собственный класс, который расширяет класс User EntityManagerImpl :
public class SpringSecurityUserManager extends UserEntityManagerImpl {
private JdbcUserDetailsManager userManager;
public SpringSecurityUserManager(
ProcessEngineConfigurationImpl processEngineConfiguration,
UserDataManager userDataManager,
JdbcUserDetailsManager userManager) {
super(processEngineConfiguration, userDataManager);
this.userManager = userManager;
}
// ...
}Этот класс нуждается в конструкторе формы выше, а также в диспетчере пользователей Spring Security. В нашем случае мы использовали поддерживаемый базой данных UserDetailsManager.
Основные методы, которые мы хотим переопределить, – это те, которые обрабатывают поиск пользователей: findById(), findUserByQueryCriteria() и findGroupsByUser().
Метод findById() использует JdbcUserDetailsManager для поиска объекта UserDetails и преобразования его в объект User :
@Override
public UserEntity findById(String userId) {
UserDetails userDetails = userManager.loadUserByUsername(userId);
if (userDetails != null) {
UserEntityImpl user = new UserEntityImpl();
user.setId(userId);
return user;
}
return null;
}Затем метод findGroupsByUser() находит все органы безопасности Spring пользователя и возвращает Список объектов группы :
public ListfindGroupsByUser(String userId) { UserDetails userDetails = userManager.loadUserByUsername(userId); if (userDetails != null) { return userDetails.getAuthorities().stream() .map(a -> { Group g = new GroupEntityImpl(); g.setId(a.getAuthority()); return g; }) .collect(Collectors.toList()); } return null; }
Метод findUserByQueryCriteria() основан на объекте UserQueryImpl с несколькими свойствами, из которого мы извлекем идентификатор группы и идентификатор пользователя, поскольку у них есть корреспонденты в Spring Security:
@Override public ListfindUserByQueryCriteria( UserQueryImpl query, Page page) { // ... }
Этот метод следует принципу, аналогичному описанному выше, путем создания User объектов из UserDetails объектов. См. Ссылку GitHub в конце для полной реализации.
Аналогично, у нас есть метод find User CountByQuery Criteria() :
public long findUserCountByQueryCriteria(
UserQueryImpl query) {
return findUserByQueryCriteria(query, null).size();
}Метод CheckPassword() всегда должен возвращать значение true, так как проверка пароля не выполняется действием:
@Override
public Boolean checkPassword(String userId, String password) {
return true;
}Для других методов, таких как методы, связанные с обновлением пользователей, мы просто создадим исключение, поскольку это обрабатывается Spring Security:
public User createNewUser(String userId) {
throw new UnsupportedOperationException("This operation is not supported!");
}4.2. Расширить группу EntityManagerImpl
Spring Security Group Manager аналогичен классу user manager, за исключением того, что он имеет дело с группами пользователей:
public class SpringSecurityGroupManager extends GroupEntityManagerImpl {
private JdbcUserDetailsManager userManager;
public SpringSecurityGroupManager(ProcessEngineConfigurationImpl
processEngineConfiguration, GroupDataManager groupDataManager) {
super(processEngineConfiguration, groupDataManager);
}
// ...
}Здесь основным методом переопределения является метод findGroupsByUser() :
@Override public ListfindGroupsByUser(String userId) { UserDetails userDetails = userManager.loadUserByUsername(userId); if (userDetails != null) { return userDetails.getAuthorities().stream() .map(a -> { Group g = new GroupEntityImpl(); g.setId(a.getAuthority()); return g; }) .collect(Collectors.toList()); } return null; }
Метод извлекает полномочия пользователя Spring Security и преобразует их в список объектов Group .
Исходя из этого, мы также можем переопределить методы find Group By Query Criteria() и find Group By Query Criteria Count() :
@Override public ListfindGroupByQueryCriteria(GroupQueryImpl query, Page page) { if (query.getUserId() != null) { return findGroupsByUser(query.getUserId()); } return null; } @Override public long findGroupCountByQueryCriteria(GroupQueryImpl query) { return findGroupByQueryCriteria(query, null).size(); }
Другие методы, обновляющие группы, могут быть переопределены, чтобы вызвать исключение:
public Group createNewGroup(String groupId) {
throw new UnsupportedOperationException("This operation is not supported!");
}4.3. Конфигурация технологического двигателя
После определения двух классов identity manager нам нужно подключить их к конфигурации.
Пружинные стартеры автоматически настраивают SpringProcessEngineConfiguration для нас. Чтобы изменить это, мы можем использовать InitializingBean:
@Autowired
private SpringProcessEngineConfiguration processEngineConfiguration;
@Autowired
private JdbcUserDetailsManager userManager;
@Bean
InitializingBean processEngineInitializer() {
return new InitializingBean() {
public void afterPropertiesSet() throws Exception {
processEngineConfiguration.setUserEntityManager(
new SpringSecurityUserManager(processEngineConfiguration,
new MybatisUserDataManager(processEngineConfiguration), userManager));
processEngineConfiguration.setGroupEntityManager(
new SpringSecurityGroupManager(processEngineConfiguration,
new MybatisGroupDataManager(processEngineConfiguration)));
}
};
}Здесь существующая processEngineConfiguration изменена для использования наших пользовательских менеджеров удостоверений.
Если мы хотим установить текущего пользователя в действие, мы можем использовать метод:
identityService.setAuthenticatedUserId(userId);
Имейте в виду, что это устанавливает Свойство ThreadLocal , поэтому значение отличается для каждого потока.
5. Заключение
В этой статье мы рассмотрели два способа интеграции активности с Spring Security.
Полный исходный код можно найти на GitHub .