org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal' with cipher instance [javax.crypto.Cipher@4e025e0a]. at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462) at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:445) at org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:390) at org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:382) at org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeManager.java:482) at org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(AbstractRememberMeManager.java:419) at org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(AbstractRememberMeManager.java:386) 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:346) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption. at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975) at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853) at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) at javax.crypto.Cipher.doFinal(Cipher.java:2164) at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:459) ... 35 more
每次登錄都會報這個錯誤,嘗試了不少次都沒解決,代碼重編譯後清除瀏覽器cookie登錄就會出現這個報錯,雖然不影響登錄可是看着很不爽!!!!java
問題產生的緣由是rememberMe的cookie在第二次打開頁面後shiro沒法解密,通過查詢資料以及代碼跟蹤發現了緣由所在web
先附上rememberMe管理器配置spring
@Bean public CookieRememberMeManager cookieRememberMeManager() { CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); simpleCookie.setMaxAge(259200000); cookieRememberMeManager.setCookie(simpleCookie); return cookieRememberMeManager; }
而後跟蹤管理器源碼發現,rememberMeManager繼承了AbstractRememberMeManager,然而AbstractRememberMeManager的構造方法中每次都會從新生成對稱加密密鑰!!!!意味着每次重啓程序都會從新生成一對加解密密鑰!!!apache
public AbstractRememberMeManager() { this.serializer = new DefaultSerializer<PrincipalCollection>(); AesCipherService cipherService = new AesCipherService(); this.cipherService = cipherService; setCipherKey(cipherService.generateNewKey().getEncoded()); } public void setCipherKey(byte[] cipherKey) { //Since this method should only be used in symmetric ciphers //(where the enc and dec keys are the same), set it on both: setEncryptionCipherKey(cipherKey); setDecryptionCipherKey(cipherKey); }
這就會致使了,第一次啓動程序shiro使用A密鑰加密了cookie,第二次啓動程序shiro從新生成了密鑰B,當用戶訪問頁面時,shiro會用密鑰B去解密上一次用密鑰A加密的cookie,致使解密失敗,致使報錯,因此這不影響用戶登陸操做(rememberMe失效罷了),因此這種異常只會在程序重啓(shiro清除session)第一次打開頁面的時候出現瀏覽器
解決辦法:tomcat
既然每次重啓都會從新生成一對密鑰,那咱們就手動設置一個加解密密鑰,主動設置cipherkey!!xml配置方式cookie
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('6ZmI6I2j5Y+R5aSn5ZOlAA==')}"/> <property name="cookie" ref="rememberCookie"/> </bean>