JwtGenerator: authenticationTime不能为空

后端开发 2026-07-09

就在将SpringBoot更新到4.0.6之后,我的 spring-boot-starter-oauth2-authorization-server 一直出现以下异常:

java.lang.IllegalArgumentException: authenticationTime cannot be null
    at org.springframework.util.Assert.notNull(Assert.java:182)
    at org.springframework.security.oauth2.server.authorization.token.JwtGenerator.getAuthenticationTime(JwtGenerator.java:237)
    at org.springframework.security.oauth2.server.authorization.token.JwtGenerator.generate(JwtGenerator.java:147)
    at org.springframework.security.oauth2.server.authorization.token.JwtGenerator.generate(JwtGenerator.java:66)
    at org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator.generate(DelegatingOAuth2TokenGenerator.java:60)
    at org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationProvider.authenticate(OAuth2AuthorizationCodeAuthenticationProvider.java:274)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:183)
    at org.springframework.security.authentication.ObservationAuthenticationManager.lambda$authenticate$1(ObservationAuthenticationManager.java:55)
    at io.micrometer.observation.Observation.observe(Observation.java:634)
    at org.springframework.security.authentication.ObservationAuthenticationManager.authenticate(ObservationAuthenticationManager.java:54)
    at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter.doFilterInternal(OAuth2TokenEndpointFilter.java:170)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)

要点摘要

如果你在securityContext中设置了任何 AbstractAuthenticationToken 的实例,它必须包含一个带有 issuedAt 时间的权限:

new UsernamePasswordAuthenticationToken("some name", "some credentials", List.of(
        FactorGrantedAuthority.withAuthority("Some Authority")
                        .issuedAt(Instant.now())
        .build()
));

说明

问题出在Spring Boot 4.0.6 也将 spring-boot-starter-oauth2-authorization-server 的版本更新到了 7.0.5

在7.0.5版本中,JwtGenerator 类不再像在 7.0.4 那样从请求中获取 authenticationTime

claimsBuilder.claim(IdTokenClaimNames.AUTH_TIME, sessionInformation.getLastRequest());

而是现在使用以下逻辑:

claimsBuilder.claim(IdTokenClaimNames.AUTH_TIME, getAuthenticationTime(context.getPrincipal()));

//...

static Date getAuthenticationTime(Authentication authentication) {
    Instant authenticationTime = null;
    for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
        if (grantedAuthority instanceof FactorGrantedAuthority factorGrantedAuthority) {
            if (authenticationTime == null || factorGrantedAuthority.getIssuedAt().isAfter(authenticationTime)) {
                authenticationTime = factorGrantedAuthority.getIssuedAt();
            }
        }
    }
    Assert.notNull(authenticationTime, "authenticationTime cannot be null");
    return Date.from(authenticationTime);
}

因此现在它试图从权限列表中读取authenticationTime,如果在某处有人手动设置了身份验证对象(因为各种自定义逻辑),这将不起作用。

简而言之,像这样的做法不再起作用:

new UsernamePasswordAuthenticationToken("some name", "some credentials", List.of());

现在它必须包含issuedAt,例如:

new UsernamePasswordAuthenticationToken("some name", "some credentials", List.of(
        FactorGrantedAuthority.withAuthority("Some Authority")
                .issuedAt(Instant.now())
                .build()
));
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章