Spring Cloud中如何保證各個微服務之間呼叫的安全性(下篇)

猿天地發表於2019-03-01

上篇文章 Spring Cloud中如何保證各個微服務之間呼叫的安全性 我們介紹了各個微服務之間呼叫認證的方式以及原理

今天我們繼續接著上篇文章來聊一聊如何能夠在呼叫方實現token的自動設定以及重新整理

我們的認證token是放在請求頭中的,相對於把token放在請求引數中更為友好,對業務介面無侵入性

但是這種方式如果需要自己設定token就麻煩了,如果是引數的形式,那麼在呼叫的時候就把獲取的token當做引數傳就可以了

House getHouseInfo(Long id, String token);
複製程式碼

傳參的方式不好的就是每個介面需要增加一個引數的定義

/**
 * 獲取房產資訊
 * @param houseId 房產編號
 * @return 
 */
@GetMapping("/{houseId}/{token}")
public ResponseData hosueInfo(@PathVariable("houseId")Long houseId,@PathVariable("token")String token) {
	return ResponseData.ok(houseService.getHouseInfo(houseId));
}
複製程式碼

或者下面這種方式

/**
 * 獲取房產資訊
 * @param houseId 房產編號
 * @return 
 */
@GetMapping("/")
public ResponseData hosueInfo(Long houseId,String token) {
	return ResponseData.ok(houseService.getHouseInfo(houseId));
}
複製程式碼

如果是PathVariable這種方式,引數是必傳的,不然無法進入介面內,如果是RequestParam這種方式,方法中不定義token引數,我估計也是可以的,至少不會報錯,反正我們是統一的去判斷有無許可權

所以說我們的token放在請求頭中,是非常友好的

接下來我們說說使用的問題

在呼叫介面的時候怎麼往請求頭中新增token呢?

每次呼叫的地方都去新增token是不是太煩了?

其實在Zuul中我們可以用過濾器來統一新增token,這個時候可以使用置前的過濾器pre

**
 * 呼叫服務前新增認證請求頭過濾器
 *
 * @author yinjihuan
 * @create 2017-11-07 16:06
 **/
public class AuthHeaderFilter extends ZuulFilter {

    public AuthHeaderFilter() {
        super();
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.addZuulRequestHeader("Authorization", TokenScheduledTask.token);
        return null;
    }
}
複製程式碼

這樣在每個請求轉發到具體的微服務之前,我們給它新增了token資訊,這個token資訊是我們從TokenScheduledTask獲取的

TokenScheduledTask是怎麼獲取token的呢?

/**
 * 定時重新整理token
 *
 * @author yinjihuan
 * @create 2017-11-09 15:39
 **/
@Component
public class TokenScheduledTask {
    private static Logger logger = LoggerFactory.getLogger(TokenScheduledTask.class);

    public final static long ONE_Minute = 60 * 1000 * 60 * 20;

    public static String token = "";

    @Autowired
    private AuthService authService;

    /**
     * 重新整理Token
     */
    @Scheduled(fixedDelay = ONE_Minute)
    public void reloadApiToken() {
        token = authService.getToken();
        while (StringUtils.isBlank(token)) {
            try {
                Thread.sleep(1000);
                token = authService.getToken();
            } catch (InterruptedException e) {
                logger.error("", e);
            }
        }
    }

}

複製程式碼

原來是一個定時任務,通過呼叫認證的方法來獲取認證好的token

##為什麼要做成定時的呢

如果按照一般的做法那就是請求之後都去獲取一次token, 這種方式是最不好的,效能太差

稍微好點那就是在獲取的地方加上快取,貌似不錯,但是有個問題是在併發的時候會存在N個請求去獲取token,這邊需要控制下

定時的就不存在上面的問題了,但是一定要確保定時任務的正常

我這邊一個token的失效時間為24小時,所以我這邊重新整理的間隔是20小時,也就是說在token還沒過期之前,我會自動重新整理成最新的,這樣就不會出現token過期的問題了

while迴圈是為了確保token能夠正確的重新整理成功

同時這個任務是在專案啟動之後立馬去重新整理token的,這樣就能確保剛過來的請求不會受到影響

具體程式碼可以參考我的github:

github.com/yinjihuan/s…

更多技術分享請關注微信公眾號:猿天地

image.png

相關文章