简体   繁体   中英

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." that happens because it is being retrieved from the Spring Boot Thread Pool with the previous values set.

I'm using Spring Webflux.

Where can I hook this SecurityAuthorizationContext.clean() call?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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