Postman发请求
网关------》A服务 携带JWT做认证ok
网关------》B服务 携带JWT做认证OK,
网关------》A服务----Feign(调用)-----》B服务 Full authentication is required to access this resource
分析:
a.因为Feign在服务之间相互调用如果需要认证,需要实现RequestInterceptor,在每次请求的时候header里面增加(token、oauthToken、Authorization),但是发现单单给header里面增加(token、oauthToken、Authorization),还是会报认证错误。于是把A服务请求中所有header放入RequestInterceptor实现代码中就ok了。
之前的拦截器代码:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Feign统一Token拦截器
*/
@Component
public class FeignTokenInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
if(null==getHttpServletRequest()){
//此处省略日志记录
return;
}
//将获取Token对应的值往下面传
requestTemplate.header("Authorization", getHeaders(getHttpServletRequest()).get("Authorization"));
}
private HttpServletRequest getHttpServletRequest() {
try {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
} catch (Exception e) {
return null;
}
}
/**
* Feign拦截器拦截请求获取Token对应的值
* @param request
* @return
*/
private Map<String, String> getHeaders(HttpServletRequest request) {
Map<String, String> map = new LinkedHashMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
return map;
}
}
改动后代码:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Feign统一Token拦截器
*/
@SuppressWarnings("Duplicates")
@Component
public class FeignTokenInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
if (null == getHttpServletRequest()) {
// 此处省略日志记录
return;
}
// 将获取Token对应的值往下面传
Map<String, String> headersMap = getHeaders(getHttpServletRequest());
if (headersMap != null && headersMap.size() > 0) {
Set<Entry<String, String>> entrySet = headersMap.entrySet();
for (Entry<String, String> entry : entrySet) {
String key = entry.getKey();
String value = entry.getValue();
// Authorization //headersMap.get("Authorization")
requestTemplate.header(key, value);
}
}
}
private HttpServletRequest getHttpServletRequest() {
try {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
} catch (Exception e) {
return null;
}
}
/**
* Feign拦截器拦截请求获取Token对应的值
*
* @param request
* @return
*/
private Map<String, String> getHeaders(HttpServletRequest request) {
Map<String, String> map = new LinkedHashMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
return map;
}
}
b.线程隔离策略设置为信号量,默认线程
hystrix.command.default.execution.isolation.strategy=SEMAPHORE
官方文档:
如果你需要在你的程序中使用ThreadLocal绑定变量,您需要将Hystrix的线程隔离策略设置为“信号量”或在Fegin中禁用Hystrix
# To disable Hystrix in Feign(禁用断路器,这样将不会走服务降级,之前想调用放返回调用失败异常)
feign.hystrix.enabled=false
# To set thread isolation to SEMAP(设置线程隔离策略为信号量)
hystrix.command.default.execution.isolation.strategy=SEMAPHORE
微信公众号
JAVA程序猿成长之路
分享学习资源,学习方法,记录程序员生活。