首页 > 解决方案 > Hibernate PersistenceBag 上的 Spring Security @PostFilter 导致删除

问题描述

一般来说,我们在服务器中有一个使用 Spring Boot 2.0.2(包含 Spring Data 和 Spring Security)的客户端-服务器应用程序。

我们有一个具有以下实现的自定义用户对象:

@Entity
@Table(name="USERS")
public class User implements Serializable {

   @Id
   @Column(name="ID")
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private int id;

   @Column(name="USERNAME", unique = true)
   private String username;

   @Column(name="PASSWORD")
   private String password;

   @ManyToMany(fetch = FetchType.LAZY)
   @Cascade(CascadeType.SAVE_UPDATE)
   @JoinTable
   (
       name="USER_INITSTATES",
       joinColumns={ @JoinColumn(name="USER_ID", referencedColumnName="ID") },
       inverseJoinColumns={ @JoinColumn(name="INITSTATE_ID", referencedColumnName="ID") }
   )
   private List<InitState> initStates = new ArrayList<>();

   public List<InitState> getInitStates() {
      return initStates;
   }
}

我们有以下实现来检索InitState当前登录用户的(客户端的某种配置对象):

@PostFilter("false")
public List<InitState> loadActiveUserInitStates() {
    if (SecurityContextHolder.getContext().getAuthentication() != null) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String currentPrincipalName = authentication.getName();

        User user = userService.findByUsername(currentPrincipalName);
        return user.getInitStates(); 
    }
    return null;
}

有问题的部分是我们返回的地方user.getInitStates()。由于User.initStates-variable 配置FetchType.LAZY了列表,因此 hibernate/jpa 将其作为持久性包返回。现在,当 Spring Security 在通过 -annotation 检索后评估列表时,@PostFilter它会遍历列表并过滤掉未授予访问权限的对象(当然,我们有一个更复杂的表达式,false但作为示例,它会这样做)。当过滤后的列表返回给调用者时,hibernate 想要持久化列表并InitStates从 -object 中删除所有 -references User

我的两个问题是: * 为什么 Hibernate 在没有任何显式调用的情况下保留列表?有没有关于这种行为的文档?*(如何)我可以配置/禁用此行为吗?

标签: springhibernatespring-bootspring-securityspring-data

解决方案


推荐阅读