使用带有 Shiro 的 RememberMe 令牌标记不匹配

Posted

技术标签:

【中文标题】使用带有 Shiro 的 RememberMe 令牌标记不匹配【英文标题】:Tag Mismatch using RememberMe token with Shiro 【发布时间】:2021-06-29 14:40:39 【问题描述】:

在我网站的几个版本之前,我开始在我的错误日志中一遍又一遍地收到以下警告。

Message:
Delegate RememberMeManager instance of type [org.apache.shiro.web.mgt.CookieRememberMeManager] threw an exception during getRememberedPrincipals().

Exception:
org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal' with cipher instance [Cipher.AES/GCM/NoPadding, mode: decryption, algorithm from: SunJCE].
    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:613)
    at org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecurityManager.java:501)
    at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:347)
    at org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:845)
    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.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:141)
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at ch.qos.logback.classic.helpers.MDCInsertingServletFilter.doFilter(MDCInsertingServletFilter.java:49)
    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:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: javax.crypto.AEADBadTagException: Tag mismatch!
    at java.base/com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:623)
    at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1118)
    at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1055)
    at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:855)
    at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2207)
    at org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:459)
    ... 51 common frames omitted

在此期间,我没有更改我的 RememberMe 令牌(我知道),例如我的密码密钥。我确实尝试使我的支持库保持最新,因此可能是其中一个升级导致了这种情况,但我没有真正的想法。奇怪的是,我的网站似乎没有受到影响,没有人报告说 RememberMe 令牌不记得它们的问题。我很想知道发生了什么,这样我就可以摆脱这些警告,再次对我的网站感到安全。非常感谢任何帮助。以下是我目前正在使用的一些相关的 3rd-party 包...

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.7.0</version>
        </dependency>

        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-spring</artifactId>
          <version>1.7.0</version>
        </dependency>

        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>5.3.0</version>
        </dependency>

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <version>2.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-jdbc</artifactId>
            <version>2.4.1</version>
        </dependency>

更新:

我应该说我的Remember Cookie是通过以下代码配置的:

@Configuration
public class SpringBeanConfigurer 
    @Bean
    public org.apache.shiro.mgt.SecurityManager securityManager() 
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(<myRealm>;

        CookieRememberMeManager rmm = new CookieRememberMeManager();
        rmm.setCipherKey(Base64.decode(<cipher key string>));
        securityManager.setRememberMeManager(rmm);

        return securityManager;
    

【问题讨论】:

【参考方案1】:

我会做一些猜测假设。

该消息已记录,但请求没有失败? 您最近从 Shiro

如果是这样,这听起来可能与 CVE-2019-12422 有关 因此,默认的记住我加密格式已更改。 虽然我们建议您不要恢复到以前的格式,但在本期中有关于如何执行此操作的说明:https://issues.apache.org/jira/browse/SHIRO-730

【讨论】:

是的,这正是我所看到的。如前所述,异常被记录为警告,由于没有人抱怨该站点,我假设所有请求都在继续。所以,我当然可以恢复,但由于不建议这样做,我能做些什么来让它按照现在的预期方式工作?没有说明。我没有使用任何配置文件,所以使用默认值。 我已更新显示我如何配置我的 CookieRememberMeManager。 当用户在访问您的网站时显示“旧的”记住我的 cookie 时会出现警告。如果用户未登录,Shiro 将删除 cookie(指示浏览器将其删除),如果用户未登录(或下次登录),则发出新的一次。 一旦您的所有用户再次登录,您将不会再看到这些警告。如果您有成千上万的用户,并且您认为此日志垃圾邮件,您可以覆盖相关方法,并以不同方式管理它:github.com/apache/shiro/blob/master/core/src/main/java/org/… 啊啊,那么它只是一个等待游戏。 :) 它似乎确实放慢了速度。所以我的用户群正在慢慢更新,如果我理解正确,这些消息最终会消失。谢谢!!

以上是关于使用带有 Shiro 的 RememberMe 令牌标记不匹配的主要内容,如果未能解决你的问题,请参考以下文章

Shiro学习(13)RememberMe

[shiro] - 加入rememberMe功能

Shiro中的Rememberme后出现浏览器500错误

第十三章 RememberMe——《跟我学Shiro》

Shiro RememberMe 1.2.4 反序列化命令执行漏洞复现

Shiro RememberMe 1.2.4 反序列化命令执行漏洞复现