文件名稱 | 版本號 | 作者 | 版本 | |
---|---|---|---|---|
解決問題:微服務內部通信-如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