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

Пружинная защита и резьба

Использование Spring Security с несколькими потоками. Помечено java, spring, spring security, темы.

Вступление

При использовании Spring Security для защиты наших приложений мы должны знать о его внутренней работе. Основой является Контекст безопасности , в котором хранятся данные, полученные в процессе аутентификации и необходимые для надлежащей авторизации. По определению это связано с потоком – ThreadLocal используется в качестве держателя, созданного в процессе фильтрации безопасности запроса. (читать далее) Решение, связанное с потоками, удобно, но есть один недостаток – контекст безопасности по умолчанию не распространяется на дочерние потоки. К счастью, Spring предоставляет инструменты для решения этой проблемы.

Делегирование контекста

Как указано в документации , нам предоставляется Возможность делегирования безопасности и Делегирование Контекста безопасности Исполнителю . Первый класс – это низкоуровневая оболочка для наших запускаемых экземпляров, реализованная с использованием шаблона делегирования . Он просто принимает заданный контекст и устанавливает его во время выполнения метода run() . Использование так же просто, как:

SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
    new DelegatingSecurityContextRunnable(originalRunnable, context);

Делегирование контекста безопасности исполнителю является более высокоуровневой абстракцией. Он делегирует Исполнитель экземпляры вместо Исполняемые файлы , позволяющие управлять пулами потоков с учетом контекста безопасности Spring.

В современной Java мы, скорее всего, использовали бы его с потоковым параллельным API или Завершаемое Будущее . Обе эти абстракции по умолчанию используют Java 8 по умолчанию ForkJoinPool.commonPool , что прекрасно, но обычно мы создаем пользовательские пулы, предназначенные для конкретных задач. В то время как ForkJoinPool предназначен для обработки алгоритмов “разделяй и властвуй”, крадущих работу, мы можем использовать старые добрые Исправлен пул потоков также. (читать далее)

В следующем примере показано создание пользовательского Исправлен пул потоков с Делегированием Исполнителю контекста безопасности и создание новой Завершаемой будущей задачи:

SecurityContext securityContext = SecurityContextHolder.getContext();
Executor delegatedExecutor = Executors.newFixedThreadPool(10);
Executor delegatingExecutor =
    new DelegatingSecurityContextExecutor(delegatedExecutor, securityContext);
CompletableFuture.supplyAsync(() -> veryHardTask(),delegatingExecutor);

@Асинхронные методы

Приведенный выше пример показывает делегирование контекста безопасности с помощью простых параллельных методов Java. При использовании Spring мы часто используем аннотацию @Async , чтобы наши методы выполнялись асинхронно. Он использует очень собственный SimpleAsyncTaskExecutor с собственным пулом потоков. Чтобы передать наш контекст, мы могли бы создать еще одну делегацию упаковки. Однако Spring Security снова дает нам удобный способ решения проблемы :

SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);

Это свойство может быть настроено с помощью:

@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
    methodInvokingFactoryBean.setTargetMethod("setStrategyName");
    methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
    return methodInvokingFactoryBean;
}

Это заставляет Spring обернуть своего асинхронного исполнителя делегатом безопасности Делегирование Исполнителю задачи Контекста Безопасности . Проще говоря, мы можем безопасно использовать методы @Async, не беспокоясь о контексте безопасности.

Подведение итогов

Spring Security по определению привязана к потокам, но по умолчанию не готова к использованию в многопоточной среде. Однако с помощью простых шагов мы можем решить проблему.

Оригинал: “https://dev.to/spooz/spring-security-and-threads”