Рубрики
Без рубрики

Мероприятия с весенней безопасностью

Узнайте, как интегрировать управление идентификацией действий с Spring Security.

Автор оригинала: baeldung.

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 List findGroupsByUser(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 List findUserByQueryCriteria(
  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 List findGroupsByUser(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 List findGroupByQueryCriteria(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 .