使用Spring Auditing @CreatedDate持久化实体触发ClassCastException异常
问题排查与解决
核心原因
新用户注册时,JPA审计机制会调用SpringSecurityAuditorAware获取当前审计人,但此时用户还未完成登录认证,SecurityContext中的Authentication对象对应的principal是字符串类型(默认值为"anonymousUser"),代码里直接强制转换为UserPrincipal就会抛出类型转换异常。
而初始化测试用户时,一般是在应用启动阶段执行,此时SecurityContext中没有活跃的认证信息,方法会返回Optional.empty(),审计字段会被留空(你的BaseEntity里这些字段未设置非空约束),所以不会触发错误。去掉BaseEntity继承后,审计逻辑完全不生效,自然也就没了这个问题。
修复代码
修改SpringSecurityAuditorAware,增加类型校验逻辑,只有当principal确实是UserPrincipal实例时才进行转换:
@Service public class SpringSecurityAuditorAware implements AuditorAware<Long> { @Override public @NotNull Optional<Long> getCurrentAuditor() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null || !authentication.isAuthenticated()) { return Optional.empty(); } Object principal = authentication.getPrincipal(); // 先判断类型,避免强制转换失败 if (!(principal instanceof UserPrincipal userPrincipal)) { return Optional.empty(); } return Optional.of(userPrincipal.getId()); } }
补充说明
- 注册接口本身就是匿名访问的,此时的认证是匿名认证,
principal不可能是UserPrincipal对象,必须做类型判断。 - 确认
BaseEntity中的createdBy、lastModifiedBy字段允许为null(当前代码中@Column未设置nullable=false,满足要求),这样审计信息为空时不影响数据持久化。
内容的提问来源于stack exchange,提问作者Nathan Lively
相关产品推荐
相关产品推荐

