hystrix線程切換後獲取不到安全上下文的坑

報錯

Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton

解決方案

  1. 取消熔斷
    feign.hystrix.enabled=false
  2. 切換隔離等級
    hystrix.command.default.execution.isolation.strategy=SEMAPHORE
  3. 線程間傳遞上下文
    a. hystrix.shareSecurityContext=true
    b. 注入自定義RequestInterceptor, 在請求中設定HTTP header
@Bean
public RequestInterceptor oAuth2RequestInterceptor() {
    return template -> {
        // 在org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter
        // 過濾器中,已經將OAuth2Authentication放大了請求上下文中,所以沒有使用instanceof判斷
        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) SecurityContextHolder
                .getContext().getAuthentication();
        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) oAuth2Authentication.getDetails();
        template.header("Authorization", details.getTokenType() + " " + details.getTokenValue());
    };
} 
  1. 在代碼內有線程切換的情況下(比如使用paralleStream),需要在線程內設置上下文
SecurityContext context = SecurityContextHolder.getContext();
List<Integer> list = xxxxService.findByxxxx(xxxx);
list.parallelStream().forEach(
	SecurityContextHolder.setContext(context);
	l -> xxxxClient.findByXxxx(l); // 請求其他服務的接口
);

原因

請求
獲取callable接口的實現類,可以看到獲取了父線程的上下文
在子線程獲取父線程的上下文
在新線程中先設定請求上下文
在新線程中先設定請求上下文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章