SpringSecurity+SpringDataJpa 使用@CreatedBy 填充创建者为null
条件:
在使用Spring Security和Spring Data JPA时,如果您在实体类的创建者字段上使用了@CreatedBy注解,通常情况下会自动填充当前登录用户的ID,而不是用户名。
这是因为@CreatedBy注解通常与Spring Data JPA的审计功能一起使用。当启用JPA的审计功能时,Spring Data JPA会自动管理实体类的创建者、创建时间等审计字段。而创建者字段一般会映射为用户的唯一标识符(如用户ID),以确保数据的唯一性和一致性。
在这种情况下,需要确保以下几点:
- 审计功能已正确启用:在Spring Boot的主配置类上使用@EnableJpaAuditing注解来启用JPA的审计功能。
- 创建者字段类型与用户ID匹配:创建者字段的类型应与用户ID字段的类型匹配,例如Long、Integer等。
- 配置Spring Security获取当前登录用户信息:确保已正确配置Spring Security以获取当前登录用户的信息。可以通过自定义实现org.springframework.security.core.userdetails.UserDetailsService接口来获取用户信息,并将其设置为已登录用户。
解决办法:
如果现在代码都满足上述条件,但是使用 @CreatedBy 填充时还是为null,那么下面是最终解决办法:
可以通过创建一个配置类来实现统一设置创建者字段的功能。下面是一个示例的配置类,以使用Spring Data JPA和Spring Security为前提,假设使用的别的安全框架/自己写的用户/权限代码,那么只需要修改SpringSecurityAuditorAware中 getCurrentAuditor方法就可以了。
@Configuration
@EnableJpaAuditing(auditorAwareRef = "getCurrentAuditor")
public class AuditConfig {
@Bean
public AuditorAware<String> getCurrentAuditor() {
return new SpringSecurityAuditorAware();
}
}
@NonNull
@Component
public class SpringSecurityAuditorAware implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return Optional.empty();
}
String username = authentication.getName();
return Optional.of(username);
}
}
注:首先需要满足上述条件
上述配置类中,AuditConfig用于启用JPA的审计功能,并通过auditorAwareRef属性引用auditorConfig方法返回的AuditorAware Bean。
SpringSecurityAuditorAware类实现了AuditorAware接口,并从SecurityContextHolder中获取当前认证用户的信息。在getCurrentAuditor方法中,首先检查当前认证是否存在并已通过身份验证,然后获取当前用户名作为创建者字段的值。
这样,每次保存实体时,都会自动填充创建者字段为当前登录用户,实现了统一设置的功能。