Как настроить стратегию Spring Security SecurityContextHolder?

Я использую асинхронные методы в своей службе (аннотация Spring 3 @Async). И у меня проблема - порожденный поток не имеет контекста безопасности. Причиной этого является то, что Spring Security по умолчанию использует стратегию SecurityContextHolder.MODE_THREADLOCAL для своего держателя контекста. Но мне нужно использовать стратегию SecurityContextHolder.MODE_INHERITABLETHREADLOCAL. На данный момент я настроил стратегию в моем AuthenticationSuccessHandler. Но, на мой взгляд, это не очень хорошая практика.

Итак, как я могу настроить его в файле конфигурации контекста?
Версия Spring Security 3.0.0.


person viator    schedule 12.08.2010    source источник
comment
Возможный дубликат Spring Security и @Async   -  person rince    schedule 06.01.2016
comment
Обратите внимание, что для веб-приложений это неправильный вопрос. Использование MODE_INHERITABLETHREADLOCAL может привести к тому, что пул потоков будет содержать потоки с неправильным контекстом безопасности для асинхронных задач. Лучшим подходом является использование исполнителя, который делегирует контекст безопасности при выполнении задачи. См. здесь: Spring Security и @Async (прошедшие проверку пользователи перепутаны)   -  person Bernie    schedule 26.07.2018


Ответы (4)


Вы можете установить переменную среды spring.security.strategy на MODE_INHERITABLETHREADLOCAL. У вас также может быть простой bean-компонент, который во время запуска вашего веб-приложения вызывает SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL) и инициализирует это значение в вашем файле конфигурации контекста.

SecurityContextHolder API

person Gandalf    schedule 12.08.2010
comment
Спасибо за ваш совет о простой фасоли. Но я нашел для себя более удобное решение - я добавил в свой контекст безопасности следующий код: p:targetMethod=setStrategyName p:arguments=MODE_INHERITABLETHREADLOCAL/› - person viator; 13.08.2010
comment
У меня все еще нет httpRequest.getRemoteUser() с настроенным этим компонентом. - person javadev; 26.02.2018
comment
Остерегайтесь последствий: при использовании пула потоков вы также должны использовать setTaskDecorator(), как описано здесь github.com/spring-projects/spring-security/issues/ Я думаю, что это ДЕЙСТВИТЕЛЬНО важно. - person Francois Marot; 04.11.2019
comment
@FrancoisMarot Спасибо за подсказку о пуле потоков! Это спасло мою заднюю часть. С SecurityContextHolder.MODE_INHERITABLETHREADLOCAL мой пул потоков иногда не получал пользовательский контекст. С executor.setTaskDecorator(runnable -> new DelegatingSecurityContextRunnable(runnable));, кажется, всегда так. - person Karsten Silz; 10.09.2020

Конфигурация Java для ответа @viator, если она вам поможет.

@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
    methodInvokingFactoryBean.setTargetMethod("setStrategyName");
    methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
    return methodInvokingFactoryBean;
}
person Matt Broekhuis    schedule 10.08.2015
comment
Поздний комментарий :-) Есть ли преимущество в использовании этого по сравнению с каким-то @PostConstruct где-то в классе конфигурации для обеспечения безопасности? - person hitch.united; 16.01.2017
comment
Я должен был увидеть пример. Postconstruct не сделает spring bean, поэтому я не знаю, как это сделать? - person Matt Broekhuis; 16.01.2017
comment
Я имел в виду, что внутри @PostConstruct вызывает SecurityContextHolder.setStrategyName(); Это все статично, поэтому я думаю, что это, вероятно, тоже сработает. Я должен дать ему шанс. - person hitch.united; 17.01.2017
comment
Полное объяснение приведено в отличном посте здесь dev.to/spooz/spring-security-and -потоки, охватывающие не только @Async, но и любой пользовательский поток - person David Canós; 03.01.2019
comment
@hitch.united См. этот другой ответ: stackoverflow.com/a/65353568/1026624 - person marcioggs; 18.12.2020

Немного другое решение, например @viator пишет:

<bean
        class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetClass"
            value="org.springframework.security.core.context.SecurityContextHolder" />
        <property name="targetMethod" value="setStrategyName" />
        <property name="arguments" value="MODE_INHERITABLETHREADLOCAL" />
    </bean>

Работает как шарм.

person Taras Melon    schedule 17.01.2017

Через конфигурацию Java без отражения.

import javax.annotation.PostConstruct;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContextHolder;

@Configuration
public class SecurityConfig {

  @PostConstruct
  public void enableAuthCtxOnSpawnedThreads() {
    SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
  }
}
person marcioggs    schedule 18.12.2020