feign之間傳遞oauth2?token的問題及解決方案
feign之間傳遞oauth2 token問題
在微服務(wù)架構(gòu)里,服務(wù)與服務(wù)之間的調(diào)用一般用feign就可以實(shí)現(xiàn),它是一種可視化的rpc,并且集成了ribbon的負(fù)載均衡能力,所以很受歡迎。
授權(quán)服務(wù)
在授權(quán)服務(wù)里,用戶通過用戶名密碼,或者手機(jī)和驗(yàn)證碼等方式登陸之后,在http頭里會有授權(quán)的標(biāo)識,在客戶端調(diào)用時(shí),需要添加當(dāng)時(shí)有效的token才可以正常訪問被授權(quán)的頁面。
Content-Type:application/jsonAuthorization:Bearer d79c064c-8675-4047-a119-fac692e447e8
而在業(yè)務(wù)層里,服務(wù)與服務(wù)之間使用feign來實(shí)現(xiàn)調(diào)用,而授權(quán)的代碼我們可以通過攔截器實(shí)現(xiàn),在feign請求之前,把當(dāng)前服務(wù)的token添加到目標(biāo)服務(wù)的請求頭就可以了,一般是這樣實(shí)現(xiàn)的。
/** ?* 發(fā)送FeignClient設(shè)置Header信息. ?* http://www.itmuch.com/spring-cloud-sum/hystrix-threadlocal/ ?* Hystrix傳播ThreadLocal對象 ?*/ @Component public class TokenFeignClientInterceptor implements RequestInterceptor { ? /** ? ?* token放在請求頭. ? ?* ? ?* @param requestTemplate 請求參數(shù) ? ?*/ ? @Override ? public void apply(RequestTemplate requestTemplate) { ? ? RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); ? ? if (requestAttributes != null) { ? ? ? HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); ? ? ? String token = request.getHeader(TokenContext.KEY_OAUTH2_TOKEN); ? ? ? requestTemplate.header(TokenContext.KEY_OAUTH2_TOKEN, ? ? ? ? ? new String[] {token}); ? ? } ? } }
上面的攔截器代碼沒有什么問題,也很好理解,但事實(shí)上,當(dāng)你的feign開啟了hystrix功能,如果開啟了,需要把hystrix的策略進(jìn)行修改,默認(rèn)是THREAD的,這個(gè)級別時(shí)ThreadLocal是空的,所以你的授權(quán)不能傳給feign的攔截器.
hystrix.command.default.execution.isolation.strategy: SEMAPHORE?
資源項(xiàng)目里獲取當(dāng)前用戶
在另一個(gè)項(xiàng)目,需要其它獲取當(dāng)前用戶,需要使用下面的代碼。
先配置一個(gè)授權(quán)的地址
security: ? oauth2: ? ? resource: ? ? ? id: user ? ? ? user-info-uri: http://${auth.host:localhost}:${auth.port:8002}/user # 這里是授權(quán)服務(wù)的地址,即auth-service ? ? ? prefer-token-info: false auth: ? host: localhost ?#這個(gè)不可以用eureka里的服務(wù)名,只能使用docker-compose里的服務(wù)名 ? port: 8002
下面的代碼用來獲取當(dāng)前用戶
?Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); ? ? String user = objectMapper.writeValueAsString(authentication.getPrincipal());
主要對feign的請求頭傳遞信息進(jìn)行講解分享給大家,各位多注意下!
oauth2 feign報(bào)401的錯(cuò)誤
報(bào)錯(cuò)問題:
feign.FeignException: status 401 reading UserFeign#queryUser(Long,String,String,String,Integer,Integer,Integer)
解決方法
import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; @Configuration public class FeignOauth2RequestInterceptor implements RequestInterceptor { private final String AUTHORIZATION_HEADER = "Authorization"; private final String BEARER_TOKEN_TYPE = "Bearer"; @Override public void apply(RequestTemplate requestTemplate) { SecurityContext securityContext = SecurityContextHolder.getContext(); Authentication authentication = securityContext.getAuthentication(); if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails) { OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails(); requestTemplate.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue())); } } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot在項(xiàng)目停止(服務(wù)停止/關(guān)閉退出)之后執(zhí)行的方法
這篇文章主要給大家介紹了SpringBoot在項(xiàng)目停止(服務(wù)停止/關(guān)閉退出)之后執(zhí)行的兩種方法,實(shí)現(xiàn)DisposableBean接口和使用@PreDestroy注解,文中有詳細(xì)的代碼講解,具有一定的參考價(jià)值,需要的朋友可以參考下2023-12-12使用 Spring Boot 2.0 + WebFlux 實(shí)現(xiàn) RESTful API功能
什么是 Spring WebFlux, 它是一種異步的, 非阻塞的, 支持背壓(Back pressure)機(jī)制的Web 開發(fā)框架.下面通過本文給大家介紹使用 Spring Boot 2.0 + WebFlux 實(shí)現(xiàn) RESTful API功能,需要的朋友參考下吧2018-01-01Spring Boot定時(shí)任務(wù)單線程多線程實(shí)現(xiàn)代碼解析
這篇文章主要介紹了Spring Boot定時(shí)任務(wù)單線程多線程實(shí)現(xiàn)代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08解決Required request body is missing錯(cuò)誤的問題
這篇文章主要介紹了解決Required request body is missing錯(cuò)誤的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06JavaEE中struts2實(shí)現(xiàn)文件上傳下載功能實(shí)例解析
這篇文章主要為大家詳細(xì)介紹了JavaEE中struts2實(shí)現(xiàn)文件上傳下載功能實(shí)例,感興趣的小伙伴們可以參考一下2016-05-05Springboot的spring-boot-maven-plugin導(dǎo)入失敗的解決方案
這篇文章主要介紹了Springboot的spring-boot-maven-plugin導(dǎo)入失敗的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07