Spring数据和Spring安全集成

Spring数据和Spring安全集成,spring,spring-security,integration,spring-data,Spring,Spring Security,Integration,Spring Data,该文档说,通过引入SecurityEvaluationContextExtension类型的bean,它将提供所有commons内置的安全表达式,如“principal”、“hasRole”等。该示例显示了在@Query中使用“principal”的简单集成 @Query("select m from Message m where m.to.id = ?#{ principal?.id }") 现在,如果我想选择所有消息,而不管“m.to.id”是什么,如果主体具有“ADMIN”或类似角色,

该文档说,通过引入SecurityEvaluationContextExtension类型的bean,它将提供所有commons内置的安全表达式,如“principal”、“hasRole”等。该示例显示了在@Query中使用“principal”的简单集成

@Query("select m from Message m where m.to.id = ?#{ principal?.id }")
现在,如果我想选择所有消息,而不管“m.to.id”是什么,如果主体具有“ADMIN”或类似角色,该怎么办。我尝试了这些方法,但只遇到了spring数据解析查询时出现的错误

@Query("select m from Message m where m.to.id = ?#{ principal?.id } or hasRole('ADMIN')")

@Query("select m from Message m where m.to.id = ?#{ principal?.id } or 'true' = ?#{ hasRole('ADMIN') }")

@Query("select m from Message m where m.to.id = ?#{ principal?.id } or 1 = ?#{ hasRole('ADMIN') }")

我们能做到这样吗?基本上,如果用户是普通用户,那么只给他们自己的消息,但是管理员用户可以获得所有消息

我们的系统中有一个类似的用例:

在您的例子中,您可以在前面提到的SpringDataExamples项目的上下文中尝试类似的方法

存储库方法:

@Query("select o from BusinessObject o where o.owner.id = ?#{principal.id} or 1=?#{hasRole('ROLE_ADMIN') ? 1 : 0}")
List<BusinessObject> findBusinessObjectsForCurrentUserById();
一些用于验证的测试:

@Test
public void findBusinessObjectsForCurrentUserByIdShouldReturnOnlyBusinessObjectsWhereCurrentUserIsOwner(){

    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(tom,"x"));

    List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();

    assertThat(businessObjects,hasSize(1));
    assertThat(businessObjects,contains(object3));

    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(olli,"x"));

    businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();

    assertThat(businessObjects,hasSize(2));
    assertThat(businessObjects,contains(object1,object2));
}


@Test
public void findBusinessObjectsForCurrentUserByIdShouldReturnAllObjectsForAdmin(){

    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(admin,"x", Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN"))));

    List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();

    assertThat(businessObjects,hasSize(3));
    assertThat(businessObjects,contains(object1,object2, object3));
}
@Test
public void findBusinessObjectsForCurrentUserByIdShouldReturnOnlyBusinessObjectsWhereCurrentUserIsOwner(){

    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(tom,"x"));

    List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();

    assertThat(businessObjects,hasSize(1));
    assertThat(businessObjects,contains(object3));

    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(olli,"x"));

    businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();

    assertThat(businessObjects,hasSize(2));
    assertThat(businessObjects,contains(object1,object2));
}


@Test
public void findBusinessObjectsForCurrentUserByIdShouldReturnAllObjectsForAdmin(){

    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(admin,"x", Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN"))));

    List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();

    assertThat(businessObjects,hasSize(3));
    assertThat(businessObjects,contains(object1,object2, object3));
}