背景
Feign token 传递时SecurityContextHolder.getContext().getAuthentication()取不到值,导致null异常
java.lang.NullPointerException: nullat chen.learn.common.configure.ChenOAuth2FeignConfigure$1.apply(ChenOAuth2FeignConfigure.java:19) ~[classes/:na]at feign.SynchronousMethodHandler.targetRequest(SynchronousMethodHandler.java:161) ~[feign-core-10.10.1.jar:na]at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:110) ~[feign-core-10.10.1.jar:na]at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) ~[feign-core-10.10.1.jar:na]at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:109) ~[feign-hystrix-10.10.1.jar:na]at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302) ~[hystrix-core-1.5.18.jar:1.5.18]at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298) ~[hystrix-core-1.5.18.jar:1.5.18]at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.8.jar:1.3.8]at rx.Observable.unsafeSubscribe(Observable.java:10327) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.3.8.jar:1.3.8]at rx.Observable.unsafeSubscribe(Observable.java:10327) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.8.jar:1.3.8]at rx.Observable.unsafeSubscribe(Observable.java:10327) [rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100) [rxjava-1.3.8.jar:1.3.8]at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56) [hystrix-core-1.5.18.jar:1.5.18]at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47) [hystrix-core-1.5.18.jar:1.5.18]at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69) [hystrix-core-1.5.18.jar:1.5.18]at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) [rxjava-1.3.8.jar:1.3.8]at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_181]at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) [na:1.8.0_181]at java.util.concurrent.FutureTask.run(FutureTask.java) [na:1.8.0_181]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
解决方案
1、在yml文件中添加如下配置,重点是 shareSecurityContext: true
feign:hystrix:enabled: true
hystrix:shareSecurityContext: true #配置把SecurityContext对象从你当前主线程传输到Hystrix线程
2、添加 hystrix配置
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
3、配置ReuestInterceptor拦截器
public class ChenOAuth2FeignConfigure {@Beanpublic RequestInterceptor oauth2FeignRequestInterceptor() {return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate requestTemplate) {SecurityContext context = SecurityContextHolder.getContext();Object details = context.getAuthentication().getDetails();if (details instanceof OAuth2AuthenticationDetails) {String authorizationToken = ((OAuth2AuthenticationDetails) details).getTokenValue();requestTemplate.header(HttpHeaders.AUTHORIZATION, "bearer " + authorizationToken);}}};}}
4、用注解方式注入
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ChenOAuth2FeignConfigure.class)
public @interface EnableChenOauth2FeignClient {
}
5、配置使用
...
@EnableChenOauth2FeignClient
public class ChenUserApplication {...}
轻松搞定!