解決問題:微服務內部通信-如FeignClient互相調用報`401`錯誤

文件名稱 版本號 作者 qq 版本
解決問題:微服務內部通信-如FeignClient互相調用報401錯誤 v1.0.0 學生宮布 8416837 SpringBoot 2.2.6
SpringCloud Hoxton.SR4

報錯全稱

Servlet.service() for servlet [dispatcherServlet] in context with path [] 
threw exception [Request processing failed; nested exception is feign.FeignException$Unauthorized: [401] 
during [POST] to [http://abc-system/logininfor?username=admin&status=Success&message=%E7%99%BB%E5%BD%95%E6%88%90%E5%8A%9F] 

代碼

	remoteLogService.saveLogininfor(username, Constants.LOGIN_SUCCESS, "登錄成功")
	...
	@PostMapping("/logininfor")
    R<Boolean> saveLogininfor(@RequestParam("username") String username, @RequestParam("status") String status,@RequestParam("message") String message);

疑似產生的原因

請求模板資源的行爲沒有被授權

彎路、坑

分析

1)使用客戶端工具調用這個接口:
在這裏插入圖片描述
↑報同樣的錯誤。
2)在請求頭增加Token(Token獲取見教程),調用成功了:
在這裏插入圖片描述
試驗一下,亂填一個Token值,調用結果,報401錯誤:

2020-06-26 14:21:53.309 ERROR 20980 --- [nio-9201-exec-9] o.a.c.c.C.[Tomcat].[localhost]           : Exception Processing ErrorPage[errorCode=0, location=/error]

org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 : [no body]

3)說明,當前微服務內部通信需請求頭攜帶Token,但是這個操作應該是底層自動完成的呀。找一下,果然,在類OAuth2FeignRequestInterceptor.java找到了授權配置:

@Component
public class OAuth2FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();
        if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails) {
            OAuth2AuthenticationDetails dateils = (OAuth2AuthenticationDetails) authentication.getDetails();
            requestTemplate.header(HttpHeaders.AUTHORIZATION,
                    String.format("%s %s", SecurityConstants.BEARER_TOKEN_TYPE, dateils.getTokenValue()));
        }
    }
}

↑但是這個請求攔截器,爲什麼沒有生效?
4)打上斷點,Debugger調試一下:
在這裏插入圖片描述
再次登錄,不出所料,Debugger沒有進入這段代碼。也就是說:添加請求頭攔截器沒有起效!
難道必須顯式將攔截器配置到FeignClient嗎?

解決方案

1)寫新的攔截器,Java代碼,已提交:
代碼地址 點擊進入
2)將攔截器顯式配置給FeignClient
在註解新增configuration = FeignConfig.class

@FeignClient(其它配置省略, configuration = FeignConfig.class)

關於

若交流技術,請聯繫qq:8416837

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