Spring OAuth2RestTemplate getForEntity 中文亂碼解決方法

肖老闆發表於2017-04-05

Spring OAuth2RestTemplate getForEntity 中文亂碼解決方法

最近在除錯微信支付,遇到蠻多的坑,不過還好網上大多都有對應的解決方案,還算比較順利地對接好了!這裡記錄一個和微信支付過程無關的坑,也是很少人提到的。這個BUG最開始出現是由於我將微信賬號從測試號換為了正式的公眾號資訊,這也就導致之前的所有測試使用者都要重新關注微信,並且也會重新生成對應的OpenID和使用者資訊。然後呢,這時候發現只有我一個人的微信賬號可以正常進入測試系統,而其他同事的微信賬號都無法進入測試系統,並且都陷入無限迴圈重新整理的情況中。即使將資料庫中資料清空,將微信快取清理掉,仍然是我可以正常進入系統,而其他同事都不行。實在是很費解!最後實在是沒有辦法,只能在本地進行跟蹤除錯,這才發現新建使用者的介面出現了400的錯誤,裡面提示有UTF_8的編碼錯誤。然後再和同事們的微信賬號一對比,發現我的微信暱稱是拼音,而其他人都是中文,所以這也是我能夠正常進入系統的原因。接下來就是解決這個UTF_8的編碼錯誤:

最開始我搜尋OAuth2RestTemplategetForEntityutf-8相關的關鍵詞的時候,發現並沒有什麼參考資料,後來再跟進原始碼裡面看到public class OAuth2RestTemplate extends RestTemplate implements OAuth2RestOperations,而RestTemplate裡面有HttpMessageConverter,這是專門用來做HTTP RequestHTTP Response的轉換的。設定斷點跟了一下,果然發現StringHttpMessageConverter的預設字符集不是UTF_8,而是ISO-8859-1,那麼接下來覆蓋掉裡面的預設編碼字符集應該就可以解決問題了!
下面是程式碼:

//sso filter
private Filter ssoFilter(ClientResources client, String path) {
    OAuth2ClientAuthenticationProcessingFilter filter = new WeChatOAuth2ClientAuthenticationProcessingFilter(path);

    OAuth2RestTemplate template = new WeChatOAuth2RestTemplate(client.getClient(), oauth2ClientContext);

    //StringHttpMessageConverter的預設字符集是'ISO-8859-1',會導致中文亂碼,因此手動設定為'UTF_8'
    List<HttpMessageConverter<?>> converterList = template.getMessageConverters();
    HttpMessageConverter<?> converterTarget = null;
    for(HttpMessageConverter<?> item : converterList){
        if(item.getClass() == StringHttpMessageConverter.class){
            converterTarget = item;
            break;
        }
    }
    if(converterTarget != null){
        converterList.remove(converterTarget);
    }
    HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
    converterList.add(converter);

    filter.setRestTemplate(template);

    UserInfoTokenServices tokenServices = new WeChatUserInfoTokenServices(client.getResource().getUserInfoUri(), client.getClient().getClientId(), userLocalService);
    tokenServices.setRestTemplate(template);
    filter.setTokenServices(tokenServices);
    return filter;
}

果不其然,其他同事也可以正常訪問測試系統了。

上面這段程式碼是在整合微信的OAuthSpring Security,感興趣的同學可以去我們團隊的Github部落格上看看整個工程的原始碼。

為什麼我不一開始就直接本地除錯呢?因為應用微服務架構後,發現本地除錯比較麻煩,或者說我們還沒有發現比較方便的本地/遠端除錯方法!當然啦,Spring Cloud框架已經提供了一個Remote Debug這樣的東西,但是還沒空去研究啊。藉此吐槽小團隊要實踐微服務架構真是很大的挑戰!就目前這款產品的開發進度來看,至少有一個月以上的時間是花在了探索微服務架構的相關技術上面去了,這一個月對於一款新的網際網路產品來說真的是非常寶貴的。話不多說,我得去加班了:)

相關文章