org.springframework.util.Base64Utils線程安全問題


  Spring 提供的 org.springframework.util.Base64Utils 類,先會檢測JDK里是否自帶java.util.Base64,如果不帶,則 使用的是 apache 提供的org.apache.commons.codec.binary.Base64:
 

 
經過一段時間的生產試運行來看, 在多線程環境中Base64Utils會出各種異常,比如這樣的異常:
java.lang.ArrayIndexOutOfBoundsException: null 
at org.apache.commons.codec.binary.BaseNCodec.readResults(BaseNCodec.java:209) 
at org.apache.commons.codec.binary.BaseNCodec.decode(BaseNCodec.java:324) 
at org.springframework.util.Base64Utils$CommonsCodecBase64Delegate.decode(Base64Utils.java:164)
at org.springframework.util.Base64Utils.decodeFromString(Base64Utils.java:124)
...
java.lang.NullPointerException: null 
at java.lang.System.arraycopy(Native Method) 
at org.apache.commons.codec.binary.BaseNCodec.readResults(BaseNCodec.java:209) 
at org.apache.commons.codec.binary.BaseNCodec.decode(BaseNCodec.java:324) 
at org.springframework.util.Base64Utils$CommonsCodecBase64Delegate.decode(Base64Utils.java:164) 
at org.springframework.util.Base64Utils.decodeFromString(Base64Utils.java:124)
...
又或者沒拋異常,但Base64Utils.decodeFromString解出的數據已經不准確了,比如此時用它解碼出的數據或秘鑰來進行解密的話,會出類似如下異常:
  javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
 at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
 at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
 at com.sun.crypto.provider.DESedeCipher.engineDoFinal(DESedeCipher.java:294)
 at javax.crypto.Cipher.doFinal(Cipher.java:2087)
...
但具體由哪個類引起的並發,原因有待分析,可能與JDK版本、org.apache.commons.codec.binary.Base64、java.util.Base64都有關系 ,不管問題出在哪,在使用Base64Utils的地方,加上同步應該即可解決:
 synchronized (Base64Utils.class) {
            key = Base64Utils.decodeFromString(keyBase64);
}
 synchronized (Base64Utils.class) {
            rtnValue = Base64Utils.encodeToString(data);
}
或者不使用 org.springframework.util.Base64Utils,而是直接使用 apache 提供的org.apache.commons.codec.binary.Base64(相應方法:Base64.decodeBase64(keyBase64),Base64.encodeBase64String(data) ,並發環境下目前發現沒有問題,代碼參見附件!!
 
由於 synchronized  同步會引起性能問題,如果直接使用org.apache.commons.codec.binary.Base64
沒有問題的話,還是采用這種方式吧
 

 

附件列表

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM