【问题标题】:Spring Data REST filtering data based on the userSpring Data REST 根据用户过滤数据
【发布时间】:2014-07-01 16:08:12
【问题描述】:

如果我有如下的存储库设置,使用 Spring Data REST,我可以访问 /receipts 中的数据并查看所有数据。但是,我只想为用户返回数据。我有一个自定义查找器“findByStorer”可以做到这一点。我如何让 Spring Data REST 使用它并从用户那里获取存储器值而不是指定查询参数?

@RepositoryRestResource(collectionResourceRel = "receipts", path = "receipts")
public interface ReceiptRepository extends PagingAndSortingRepository<Receipt, BigDecimal> {

    @Query
    public Page<Receipt> findByStorer(String storer, Pageable pageable);
}

我还没有实现任何安全性,所以这个问题目前更多的是理论而不是实践。

谢谢。

【问题讨论】:

    标签: spring rest spring-mvc


    【解决方案1】:

    基于@rpr 的回答:

    您应该能够引用连接实体(Storer)的属性。在您的示例中,如果您有 Receipt -> Storer -> User 您可以查询 Storer.user 具有从安全上下文注入的值的 Receipts。

    @PreAuthorize("isFullyAuthenticated && (#userName==principal.username)")
    Page<Receipt> findByStorer_User(@Param("userName") String userName)
    

    【讨论】:

    • 我们怎样才能让这个 findByStorer_User() 方法成为默认方法,在访问受限的用户使用 API 时替换 findAll() 方法?我们希望为管理员用户保留 findAll(),并为受限用户提供有限的方法。
    【解决方案2】:

    例如,给定Repositoryfor SomeEntity,您可以使用自定义@Query 过滤方法覆盖findAll 方法,该方法按属性owner 的值为`#{principal.username} 进行过滤

    @RepositoryRestResource(path = "some-entities", collectionResourceRel = "some-entities", itemResourceRel = "some-entity")
    interface SomeEntityRepository extends PagingAndSortingRepository<SomeEntity, String> {
      @Override
      @RestResource(exported = true)
      @Query("select someEntity from SomeEntity someEntity where someEntity.owner = ?#{principal.username}")
      Iterable<SomeResource> findAll();
    }
    

    【讨论】:

      【解决方案3】:

      如果你使用 Spring Security,你可以使用这种方法:

      @PreAuthorize("isFullyAuthenticated() && (#userName == principal.username)")
      public List<User> findByUserName(@Param("userName")String userName);
      

      【讨论】:

      • 这并没有完全解释如何从用户名到存储者,例如,如果要将收据表连接到用户表,您需要通过存储者表。 IE,类似于select * from user, receipt where user.storer = receipt.storer
      【解决方案4】:

      这个问题是一个典型的横切关注点,所以我尝试应用 AOP。定义 Advice 并更新 args(字符串存储),解释如下:https://stackoverflow.com/a/46353783/1203628

      @Aspect
      @Transactional
      @Component
      public class FilterProjectsAspect {
      
      @Pointcut("execution(*  com.xxx.ReceiptRepository.findByStorer(..))")
          public void projectFindAll() {
          }
      
          @Around("projectFindAll()")
          public Object  filterProjectsByUser(final ProceedingJoinPoint pjp) throws Throwable {
      
              Object[] args = pjp.getArgs();
              for (int i = 0; i < args.length; i++) {
                  if (args[i] instanceof String) {
                      String storer=(String) args[i];
                      // Find storer by user 
                      args[i]=storer;  //Update args
                  }
              return pjp.proceed(args);
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2019-03-17
        • 2021-11-16
        • 1970-01-01
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        • 2013-12-15
        • 1970-01-01
        相关资源
        最近更新 更多