Spring-data和Spring-security集成

时间:2015-05-22 02:26:35

标签: spring spring-security integration spring-data

该文档通过引入类型为SecurityEvaluationContextExtension的bean表示,它将使所有公共内置安全表达式可用,如'principal','hasRole'等。该示例显示了在@中使用'principal'的简单集成。查询

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

现在如果我想要选择所有消息,无论'm.to.id'是什么,如果主体具有角'ADMIN'或类似的东西。我试过这些但只是遇到来自spring-data解析查询的错误

@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') }")

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

1 个答案:

答案 0 :(得分:4)

我们在spring-data-examples中有类似的用例:

@Query("select o from BusinessObject o where o.owner.emailAddress like ?#{hasRole('ROLE_ADMIN') ? '%' : principal.emailAddress}")
List<BusinessObject> findBusinessObjectsForCurrentUser();

在你的情况下,你可以尝试类似的东西(在上面提到的spring-data-examples项目的上下文中)

存储库方法:

@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));
}