简体   繁体   English

Spring Boot webflux中的线程本地remove()

[英]Thread Local remove() in Spring Boot webflux

I have a Web Filter that sets an object in a ThreadLocal attribute and I'm trying to understand how/when this Thread local should be cleaned-up (ThreadLocal.remove()) to avoid the exception "User context already initiated."我有一个 Web 过滤器,它在 ThreadLocal 属性中设置一个对象,并且我试图了解应该如何/何时清除此本地线程 (ThreadLocal.remove()) 以避免出现异常“用户上下文已经启动”。 that happens because it is being retrieved from the Spring Boot Thread Pool with the previous values set.发生这种情况是因为它是从 Spring Boot 线程池中使用先前设置的值进行检索的。

I'm using Spring Webflux.我正在使用 Spring Webflux。

Where can I hook this SecurityAuthorizationContext.clean() call?我在哪里可以挂钩这个 SecurityAuthorizationContext.clean() 调用?

public class SecurityAuthorizationContext
{
    private static final ThreadLocal<PrivilegeHolder> userContext = new ThreadLocal<>();

    private final List<String> roles;

    private SecurityAuthorizationContext(List<String> roles)
    {
        this.roles = roles;
    }

    public static void create(List<String> roles)
    {
        if (nonNull(userContext.get()))
        {
            log.error("User context already initiated.");
            throw new AuthorizationException("User context already initiated.");
        }

        PrivilegeHolder privilegeHolder = new PrivilegeHolder();
        userContext.set(privilegeHolder);

        // example of privileges retrieved from database by the user roles
        privilegeHolder.add(INSERT);
        privilegeHolder.add(DELETE);
    }

    public static void clean()
    {
        userContext.remove();
    }

    public static boolean hasInsertPrivilege()
    {
        return userContext.get().hasPrivilege(INSERT);
    }

    public static boolean hasDeletePrivilege()
    {
        return userContext.get().hasPrivilege(DELETE);
    } 
}

public class AuthorizationFilter implements OrderedWebFilter
{
    private static final String USER_ROLES = "user-roles";

    @Override
    public int getOrder()
    {
        return SecurityWebFiltersOrder.AUTHORIZATION.getOrder();
    }

    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain)
    {
        ServerHttpRequest request = serverWebExchange.getRequest();
        HttpHeaders headers = request.getHeaders();

        List<String> roles = headers.get(USER_ROLES);

        SecurityAuthorizationContext.create(roles);

        return webFilterChain.filter(serverWebExchange);
    }        
}

@Configuration
@EnableWebFluxSecurity
@EnableTransactionManagement
public class ApplicationConfiguration
{    
    @Autowired
    private AuthorizationFilter authorizationFilter;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
    {
        return http
            .csrf().disable()
            .authorizeExchange()
            .pathMatchers("/**").permitAll()
            .and()
            .addFilterAt(authorizationFilter, AUTHORIZATION)
            .build();
    }    
}

UPDATE : Long story short ... I just want to extract something from request headers and make it available to all the stack without passing it as parameter.更新:长话短说......我只想从请求标头中提取一些内容,并使其可用于所有堆栈而不将其作为参数传递。

因此,最好使用 reactor 上下文而不是 ThreadLocal,您可以在这里阅读: https : //projectreactor.io/docs/core/release/reference/#context

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM