在 Spring 数据 JPA 查询中注入用户

Injecting user on Spring Data JPA queries

我主要使用 JPA 和 Hibernate,但我对 Spring Data JPA 比较陌生。我正在尝试注入已登录的用户,以便查询对用户的可见性进行限制。

假设我们有这个实体:

public class Group {
    private String code;
    private String name;
    private String creationUserId;
}

而 CreationUserId 是实体用户的列 Id 的 FK。这试图表示只有 ID 等于此 creationUserId 的用户才能访问此组。

所以,考虑到我使用的是 JWT(令牌上的主题是用户 ID)和 springSecurity(因此用户在 SecurityContextHolder.getContext().getAuthentication() 中),是否有任何奇特的方式来做类似

public List<Groups> findMyGroups () {
    return groupsRepository.findMyGroups();
}

使用 SpringDataJPA 给我们的功能?

我尽量避免做类似

的事情
public List<Groups> findMyGroups () {
    MyUser u = (MyUser)SecurityContextHolder.getContext().getAuthentication().getDetails();
    return groupsRepository.findGroupsByUserCreationId(u.getId());
}

我这样做没有问题,但它会导致这样的样板文件,也许有一些解决方法可以实现它。

当然我不希望在每个查询中都使用这个,只是在某些查询中(有两种不同的安全角色用于列表,group:readAll 和 group:readMine)。

Spring 安全性提供与 Spring 数据的集成以实现您想要的。看看 reference documentation about that.

简而言之,您必须添加依赖项并公开一个 SecurityEvaluationContextExtension 类型的 Bean,如下所示:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-data</artifactId>
</dependency>

@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
    return new SecurityEvaluationContextExtension();
}

有了这个后,您可以在查询中使用 Authentication

@Query("SELECT g FROM Group g WHERE g.creationUserId = ?#{principal?.id}")
List<Group> readMine();