Unable to execute 'doFinal' with cipher instance [javax.crypto.Cipher@4e025e0a]

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>
相關文章
相關標籤/搜索