You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义OneTimeToken实现类触发IllegalStateException异常排查

解决No primary or single unique constructor found for interface OneTimeToken异常

1. 修正Repository的泛型参数

确保你的JPA Repository是针对具体实体类PersistentOneTimeToken而非OneTimeToken接口定义的,示例:

// 错误写法
// public interface OneTimeTokenRepository extends JpaRepository<OneTimeToken, String> { ... }

// 正确写法
public interface OneTimeTokenRepository extends JpaRepository<PersistentOneTimeToken, String> {
    Optional<PersistentOneTimeToken> findByTokenValue(String tokenValue);
}

JPA需要具体的实体类来完成实例化,使用接口作为泛型参数会导致框架尝试实例化接口,触发构造器异常。

2. 确保PersistentOneTimeToken拥有合法构造器

JPA实体必须包含无参构造器,同时可以添加全参构造器方便使用:

@Entity
public class PersistentOneTimeToken implements OneTimeToken {
    @Id
    private String tokenValue;
    private LocalDateTime expirationTime;
    private String username;
    // 其他业务字段...

    // JPA要求的无参构造器
    public PersistentOneTimeToken() {}

    // 全参构造器
    public PersistentOneTimeToken(String tokenValue, LocalDateTime expirationTime, String username) {
        this.tokenValue = tokenValue;
        this.expirationTime = expirationTime;
        this.username = username;
    }

    // 实现OneTimeToken接口的所有方法...
}

如果使用Lombok,可以用@NoArgsConstructor和@AllArgsConstructor注解替代手动编写构造器。

3. 检查OneTimeTokenService的实现逻辑

确保服务从Repository获取令牌时,返回的是PersistentOneTimeToken实例,方法返回类型可使用OneTimeToken接口实现多态,示例:

@Service
public class OneTimeTokenServiceImpl implements OneTimeTokenService {
    private final OneTimeTokenRepository tokenRepository;

    public OneTimeTokenServiceImpl(OneTimeTokenRepository tokenRepository) {
        this.tokenRepository = tokenRepository;
    }

    @Override
    public Optional<OneTimeToken> findByTokenValue(String tokenValue) {
        // 自动向上转型为OneTimeToken接口
        return tokenRepository.findByTokenValue(tokenValue);
    }

    // 其他业务方法...
}

4. 修正Security配置中的OTT组件

确保Security配置里的OneTimeTokenAuthenticationProvider等组件,依赖的是你实现的OneTimeTokenService或针对具体实体的Repository,示例:

@Configuration
public class SecurityConfig {
    @Bean
    public OneTimeTokenAuthenticationProvider oneTimeTokenAuthenticationProvider(OneTimeTokenService tokenService) {
        return new OneTimeTokenAuthenticationProvider(tokenService);
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/generate-token").permitAll()
                .anyRequest().authenticated()
            )
            .ott(ott -> ott
                .oneTimeTokenService(tokenService())
                .successHandler(oneTimeTokenSuccessHandler())
            );
        return http.build();
    }

    // 其他Bean定义...
}

5. 清理无效配置

移除PersistentOneTimeToken上的@Primary注解(实体类不需要Spring Bean的优先级标记),同时删除手动声明的OneTimeToken类型Bean——服务返回的实例已经是合法的接口实现类,无需额外声明。


内容的提问来源于stack exchange,提问作者Jeff E Mandel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 22:45:59