shiro報錯.crypto.CryptoException: Unable to correctly extract the Initialization Vector or ciphertext.
這個錯誤困擾了我很久
org.apache.shiro.crypto.CryptoException: Unable to correctly extract the Initialization Vector or ciphertext. at org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:378) at org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:489) at org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:429) at org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:396) at org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSecurityManager.java:604) at org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:492) at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:342) at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:846) at org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.java:148) at org.apache.shiro.web.servlet.AbstractShiroFilter.createSubject(AbstractShiroFilter.java:292) at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:359) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2476) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2465) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:744) Caused by: java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:370) ... 35 more
這個錯誤後面還會帶一個數組下標越界的異常,我仔細檢查了spring與shiro的配置檔案和springMVC的配置檔案,確保自己的程式碼等相關配置沒有問題,可是每次伺服器啟動就會伴隨著這個錯誤,而且是報兩次,在我進行登入認證時正常,也可以正常退出,但是後面引起了其他的問題,我不得不尋找其中的原因,網路上關於這個錯誤很少,有效的資訊少之又少。
終極解決
直接清空瀏覽器的cookie的快取,在不清楚到底是哪個快取的情況下,我建議清空所有的cookie,問題可以得到解決,極有可能是當前瀏覽器在其他的網站中有過rememberMe的記錄導致後臺的shiro會用cookie去反序列化。
錯誤原因
shiro底層有一個AbstractRememberMeManager的抽象實現,便是這個錯誤的罪魁禍首,服務端在接收cookie時,得到rememberMe的cookie值-->Base64解碼-->AES解密-->反序列化(未限制)。shiro≤1.2.4版本預設使CookieRememberMeManager,由於AES使用的key洩露,導致反序化的cookie可控,從而引發反序化攻擊。而且AbstractRememberMeManager的構造方法中每次都會重新生成對稱加密金鑰!!!!意味著每次重啟程式都會重新生成一對加解密金鑰!!!這就會導致第一次啟動程式shiro使用A金鑰加密了cookie,第二次啟動程式shiro重新生成了金鑰B,當用戶訪問頁面時,shiro會用金鑰B去解密上一次用金鑰A加密的cookie,導致解密失敗,導致報錯,所以這不影響使用者登入操作(rememberMe失效罷了),所以這種異常只會在程式重啟(shiro清除session)第一次開啟頁面的時候出現。
shiro的這個rememberMe功能有安全漏洞,詳情可以百度,最好避免在專案中的使用,尤其是敏感的資料。