在微服務架構裏,服務與服務之間的調用通常用feign就能夠實現,它是一種可視化的rpc,而且集成了ribbon的負載均衡能力,因此很受歡迎。spring
在受權服務裏,用戶經過用戶名密碼,或者手機和驗證碼等方式登錄以後,在http頭裏會有受權
的標識,在客戶端調用時,須要添加當時有效的token才能夠正常訪問被受權的頁面。docker
Content-Type:application/json Authorization:Bearer d79c064c-8675-4047-a119-fac692e447e8
而在業務層裏,服務與服務之間使用feign來實現調用,而受權的代碼咱們能夠經過攔截器實現,在feign請求以前,把當前服務的token添加到目標服務的請求頭就能夠了,通常是這樣實現的。json
/** * 發送FeignClient設置Header信息. * http://www.itmuch.com/spring-cloud-sum/hystrix-threadlocal/ * Hystrix傳播ThreadLocal對象 */ @Component public class TokenFeignClientInterceptor implements RequestInterceptor { /** * token放在請求頭. * * @param requestTemplate 請求參數 */ @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}); } } }
上面的攔截器代碼沒有什麼問題,也很好理解,但事實上,當你的feign開啓了hystrix功能,若是開啓了,須要把hystrix的策略進行修改,默認是THREAD
的,這個級別時ThreadLocal是空的,因此你的受權不能傳給feign的攔截器.架構
hystrix.command.default.execution.isolation.strategy: SEMAPHORE
在另外一個項目,須要其它獲取當前用戶,須要使用下面的代碼。app
security: oauth2: resource: id: user user-info-uri: http://${auth.host:localhost}:${auth.port:8002}/user # 這裏是受權服務的地址,即auth-service prefer-token-info: false auth: host: localhost #這個不能夠用eureka裏的服務名,只能使用docker-compose裏的服務名 port: 8002
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String user = objectMapper.writeValueAsString(authentication.getPrincipal());
本講主要對feign的請求頭傳遞信息進行講解,開發時遇到的坑總節了一下,分享給你們!負載均衡