异步feign传递token

1. 问题描述

2. 解决方案

2.1 在本项目中通过上下文获取用户信息

1
2
3
4
5
6
7
8
9
@Resource
private ResourceServerTokenServices tokenServices;

private void initLocalToken(String token) {
if(StrUtil.isNotBlank(token)) {
OAuth2Authentication auth = tokenServices.loadAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}

2.2 将token通过feign传递到下一个服务

  • 定义一个线程变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import com.alibaba.ttl.TransmittableThreadLocal;

/**
* token线程本地变量
* @author iseven.yang
* @date 2023/8/1 0:12
*/
public class CustomTokenThreadLocal {

private static final ThreadLocal<String> TOKEN_CONTEXT = new TransmittableThreadLocal<>();

/**
* 设置token
* @param token
*/
public static void setToken(String token) {
TOKEN_CONTEXT.set(token);
}

/**
* 获取token
* @param token
*/
public static String getToken() {
return TOKEN_CONTEXT.get();
}

/**
* 移除变量
*/
public static void remove() {
TOKEN_CONTEXT.remove();
}
}

  • 自定义feign组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import cn.hutool.core.util.StrUtil;
import feign.RequestTemplate;
import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.stereotype.Component;

/**
* 自定义feign传递token
* @author iseven.yang
* @date 2023/7/31 23:40
*/
@Component
public class CustomRequestInterceptor extends OAuth2FeignRequestInterceptor {

public CustomRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, OAuth2ProtectedResourceDetails resource) {
super(oAuth2ClientContext, resource);
}

@Override
public void apply(RequestTemplate template) {
String token = CustomTokenThreadLocal.getToken();
if(StrUtil.isNotBlank(token)) {
template.header("Authorization", "bearer"+token);
} else {
super.apply(template);
}
}
}

  • 代码中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
public void fun(ActionRequestDTO actionRequestDTO) {

// 初始化用户
initLocalToken(actionParam.getToken());
try {
// 传递Feign token
CustomTokenThreadLocal.setToken(actionParam.getToken());
// 执行业务
actionResult = actionParam.getAction().run(actionParam);
} finally {
CustomTokenThreadLocal.remove();
}
}
  • 本地框架中需要取消原来的传递方式
1
//@EnableOAuth2ClientFeign 取消默认的token传递方式,自定义CustomRequestInterceptor传递方式