異常描述
微服務(wù) Controller 層方法通過 Feign 調(diào)用某個微服務(wù)方法,出現(xiàn)以下異常:
feign.FeignException: status 401 reading UserFeign#updateLoginTime(Integer)
at feign.FeignException.errorStatus(FeignException.java:78)
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:93)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:149)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:78)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.sun.proxy.$Proxy103.updateLoginTime(Unknown Source)
異常原因
權(quán)限校驗(yàn)失敗
即有某個地方會校驗(yàn)該 Feign 請求的授權(quán)信息,然后未通過,返回了 401 這個錯誤碼
不一定是 Feign 本身的權(quán)限校驗(yàn),雖然是 Feign 報的異常
一開始因?yàn)槭?Feign 報的異常,我就開始找 Feign 請求攔截器等,但是一無所獲
后來發(fā)現(xiàn),是因?yàn)?Feign 請求中缺失 Cookie,導(dǎo)致被網(wǎng)關(guān)攔截器攔截
異常分析
我的安全校驗(yàn)邏輯如下: 非登錄請求進(jìn)入網(wǎng)關(guān)后,校驗(yàn) cookie,根據(jù) cookie 值,從 Redis 中取出 JWT,并存入請求頭中
每個微服務(wù)會解析請求頭中的 JWT,以此獲取登錄用戶信息
前端的請求進(jìn)入 Controller 中后,Controller 的方法再調(diào)用 Feign
此時的 Feign 請求是獲取不到請求頭的,微服務(wù)也就無法獲取登錄用戶信息
所以我在微服務(wù)中增加了 Feign 攔截器,用來增強(qiáng)請求:將前端請求中的請求頭信息存入 Feign 請求中:
/**
* Feign 調(diào)用增強(qiáng)請求頭,防止登錄信息無法傳遞而被服務(wù)攔截
*
* @author Eugenema
* @date 2022/7/30 12:05
*/
@Component
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
//獲取客戶端訪問的請求
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(requestAttributes != null){
HttpServletRequest request = requestAttributes.getRequest();
if (request != null) {
String token = request.getHeader("Authorization");
//同步到 feign 請求中
requestTemplate.header("Authorization", token);
return;
}
}
}
}
/**
* 用戶 feign 調(diào)用
*
* @author Eugenema
* @date 2022/7/23 17:16
*/
@FeignClient(contextId = "userService", name = "gatewayService", path = "/userService")
@RequestMapping("/user")
public interface UserFeign {
……
}
故,F(xiàn)eign 請求會先經(jīng)過 Feign 攔截器,將請求頭加入到請求中
然后再經(jīng)過網(wǎng)關(guān)攔截器,結(jié)果網(wǎng)關(guān)攔截器會先檢查 Cookie 是否存在:很明顯,不存在?。。?br> 于是網(wǎng)關(guān)攔截器就攔截了,然后 Feign 調(diào)用就報錯了……
異常解決
在 Feign 請求攔截器中,除了增強(qiáng)請求頭外,把 Cookie 也加上文章來源:http://www.zghlxwxcb.cn/news/detail-453236.html
/**
* Feign 調(diào)用增強(qiáng)請求頭,防止登錄信息無法傳遞而被服務(wù)攔截
*
* @author Eugenema
* @date 2022/7/30 12:05
*/
@Component
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
//獲取客戶端訪問的請求
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(requestAttributes != null){
HttpServletRequest request = requestAttributes.getRequest();
if (request != null) {
String cookie = request.getHeader("Cookie");
String token = request.getHeader("Authorization");
//同步到 feign 請求中
requestTemplate.header("Cookie", cookie);
requestTemplate.header("Authorization", token);
return;
}
}
}
}
疑問
因?yàn)楫惓J窃?Feign 中報出來的,且我的網(wǎng)關(guān)攔截器是會對攔截下來的請求打印日志的
但是網(wǎng)關(guān)當(dāng)時并沒有日志打印,所以一開始沒有往這邊想
不太清楚是因?yàn)樯?span toymoban-style="hidden">文章來源地址http://www.zghlxwxcb.cn/news/detail-453236.html
到了這里,關(guān)于Feign 調(diào)用出現(xiàn)異常:feign.FeignException: status 401 reading xxx#xxx(xxx)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!