Spring Data Rest:基于安全性的投影

时间:2015-03-01 13:37:09

标签: spring-security jackson spring-data-jpa spring-data-rest

我正在使用当前版本的Spring Data RestSpring Data JPA并拥有以下实体:

public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private String password;
    private String email;
   ...getter/setter methods...
}

我也在使用Spring Security

我的用户存储库:

   @RepositoryRestResource(
     collectionResourceRel = "user", 
     path = "user", 
    excerptProjection = UserSimpleProjection.class)
public interface UserRepository extends PagingAndSortingRepository<User, Long> {

}

例如:

  • 用户1已登录
  • 用户1请求http://localhost:8080/user/1 - 所有字段均可见
  • 用户1请求http://localhost:8080/user/2 - 只有idname可见。

我和杰克逊尝试了不同的解决方案,没有一个能解决我的问题:

  • 使用JsonView:我发现无法更改ObjectMapper的视图,具体取决于登录的用户
  • 按照here所述实施了不同的Jackson过滤器,但我发现无法更改ObjectMapper配置以解决不同的请求。

然后我找到Projections

我创建了一个投影:

@Projection(name = "simple", types = User.class)
public interface UserSimpleProjection {

    public Long getId();

    public String getName();
}

和另一个详细的:

@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{

    public String getEmail();
}

到目前为止,根据我的要求,我会得到不同的结果。

有没有办法根据Spring Security自动切换投影和/或限制不同角色的不同投影?

3 个答案:

答案 0 :(得分:17)

您可以在投影中添加“虚拟”值属性,以使用安全检查调用服务方法:

@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{

    @Value("#{@userService.checkAccess(target)? target.email : null}")
    public String getEmail();
}

如果您的自定义UserService组件返回true,那么应该公开电子邮件,或者只需@PreAuthorize checkAccess(..) AccessDeniedException就可以提出target你。

注意,SpEL中的href="../stylesheets/stylesheet.css" 属性包含原始对象 - 由Spring-DATA提供。

答案 1 :(得分:2)

您也可以使用Spring Security配置中的RegexRequestMatcher执行此操作:

.regexMatchers(HttpMethod.GET,"/user/.*projection=simple.*").hasRole("ROLE_ADMIN")

答案 2 :(得分:0)

不,Spring Data REST预测不支持此功能。