Spring security 使用spring security AuditorAware的spring数据jpa应用程序中的StackOverflowException
我的spring后端有一个非常讨厌的StackOverflowException,我需要帮助。这是不容易解决的。我真的希望能在这里找到一些帮助 我后端工作的大部分内容。我可以查询REST接口中的模型,SpringHateOAS、GET、PUT和POST操作很好地返回了这些模型。但有一个例外:当我尝试更新现有的Spring security 使用spring security AuditorAware的spring数据jpa应用程序中的StackOverflowException,spring-security,spring-data,spring-data-jpa,Spring Security,Spring Data,Spring Data Jpa,我的spring后端有一个非常讨厌的StackOverflowException,我需要帮助。这是不容易解决的。我真的希望能在这里找到一些帮助 我后端工作的大部分内容。我可以查询REST接口中的模型,SpringHateOAS、GET、PUT和POST操作很好地返回了这些模型。但有一个例外:当我尝试更新现有的DelegationModel时,我会遇到一个无止境的StackOverflowException 这是我的DelegetionModel.java类。请注意,该委托模型实际上没有任何带有@
DelegationModel
时,我会遇到一个无止境的StackOverflowException
这是我的DelegetionModel.java
类。请注意,该委托模型实际上没有任何带有@CreatedBy注释的属性
@Entity
@Data
@NoArgsConstructor
@RequiredArgsConstructor(suppressConstructorProperties = true) //BUGFIX: https://jira.spring.io/browse/DATAREST-884
@EntityListeners(AuditingEntityListener.class) // this is necessary so that UpdatedAt and CreatedAt are handled.
@Table(name = "delegations")
public class DelegationModel {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
/** Area that this delegation is in */
@NonNull
@NotNull
@ManyToOne
public AreaModel area;
/** reference to delegee that delegated his vote */
@NonNull
@NotNull
@ManyToOne
public UserModel fromUser;
/** reference to proxy that receives the delegation */
@NonNull
@NotNull
@ManyToOne
public UserModel toProxy;
@CreatedDate
@NotNull
public Date createdAt = new Date();
@LastModifiedDate
@NotNull
public Date updatedAt = new Date();
}
如中所述,我实现了必要的AuditorAware接口,该接口从SQL DB加载用户模型。我原以为只有在具有用@CreatedBy
注释的字段的模型中才会调用此AuditorAware接口
@Component
public class LiquidoAuditorAware implements AuditorAware<UserModel> {
Logger log = LoggerFactory.getLogger(this.getClass()); // Simple Logging Facade 4 Java
@Autowired
UserRepo userRepo;
@Override
public UserModel getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
log.warn("Cannot getCurrentAuditor. No one is currently authenticated");
return null;
}
User principal = (org.springframework.security.core.userdetails.User) authentication.getPrincipal();
UserModel currentlyLoggedInUser = userRepo.findByEmail(principal.getUsername()); // <<<<======= (!)
return currentlyLoggedInUser;
} catch (Exception e) {
log.error("Cannot getCurrentAuditor: "+e);
return null;
}
}
}
由于某种原因,我看不出来,这实际上调用了上面的AuditorAware实现。现在的问题是,我的LqiuidoAuditorAware实现在无休止的循环中一次又一次地被调用。似乎LiquidoAuditorAware.java中的UserModel查询再次调用了LiquidoAuditorAware。(这是不寻常的,因为这只是来自DB的读取操作。)
这是你的电话号码
所有代码都可以在此找到
我真的需要任何帮助。我在黑暗中搜索:-)您看到这种行为的原因是,
AuditorAware
实现是从JPA@PrePersist
/@PreUpdate
回调中调用的。现在通过调用findByEmail(…)
发出一个查询,这将再次触发脏检测,从而触发刷新,从而调用回调
建议的解决方法是将UserModel
的实例保留在Spring SecurityUser
实现中(在UserDetailsService
在身份验证时查找实例时进行查找),这样就不需要额外的数据库查询
另一个(不太推荐的)解决方法是将
EntityManager
注入到AuditorAware
实现中,在查询执行之前调用setFlushMode(FlushModeType.COMMIT)
,然后将其重置为FlushModeType.AUTO
,这样查询执行时不会触发刷新。非常感谢您的快速回答!我有点高兴,我最初的猜测是正确的,AuditorAware内部的查询才是问题所在。但我没有看到解决办法。我会这么做的。仅供参考:刚刚在一分钟前发现了一个非常类似的问题:Oliver,这仍然是推荐的方法,还是在spring security或spring data jpa的更高版本中已经修复了?
@RestController
@RequestMapping("/liquido/v2/users")
public class UserRestController {
[...]
@RequestMapping(value = "/saveProxy", method = PUT, consumes="application/json")
@ResponseStatus(HttpStatus.CREATED)
public @ResponseBody String saveProxy(
@RequestBody Resource<DelegationModel> delegationResource,
//PersistentEntityResourceAssembler resourceAssembler,
Principal principal) throws BindException
{
[...]
DelegationModel result = delegationRepo.save(existingDelegation);
[...]
}
[...]
}