放宽Spring Data REST投影的安全性

5

我有一个用户类,我想授权访问,以便只有用户可以看到他被授权的内容。

使用Spring Security与Spring Data Rest相结合,在JPA Repository中实现以下内容,这很容易实现 -

public interface UserRepository extends JPARepository<User,Integer> {

    @PreAuthorize("hasRole('LOGGED_IN') and principal.user.id == #id")
    User findOne(@Param("id") Integer id);

}

以这种方式,当用户访问像Spring Data REST脚手架URL这样的网址时 -
/users/{id}
/users/{id}/userPosts

只有使用{ id }登录的用户才能看到这些内容,其他人都会得到401错误提示,就像我想要的那样。

我的问题是,我有一个投影(Projections),它是每个用户的公共视图,我正在使用Spring Data Rest投影来创建它,如下所示,我希望每个{ id }都可以访问:

@Projection(name = "details", types = User.class)
public interface UserDetailsProjection {
..
}

所以,/users/{id1}?projection=details/users/{id2}?projection=details 应该返回200 OK并显示数据,即使用户已经登录为 {id1}
我开始通过使用 @PreAuthorize("permitAll") 对投影进行标记来实现这一点,但这不会起作用,因为存储库具有更严格的安全检查。我们可以在投影中放宽安全性,实现此功能吗?
我正在使用最新的Spring Data Rest和Spring Security发行版。
2个回答

2

针对这种情况,添加一个自定义控制器是合理的。

请考虑以下内容:

  • 使用 @Value 注释在投影中评估访问权限
  • 为相同数据库数据添加另一个实体,但具有不同的字段集用于只读操作,例如使用继承(请注意缓存等问题)- 取决于您的数据存储类型
  • 修改模型以将 User 实体拆分为两个不同的实体(配置文件、帐户),因为它们似乎具有不同的访问权限,甚至可能有不同的操作
  • 您还可以添加 ResourceProcessor<UserSummaryProjection> 以编程方式评估访问权限,并使用 DTO 替换资源内容(投影)

使用 @Value 注释评估投影中的访问权限示例:

@Projection(types = User.class, name = "summary")
public interface UserSummaryProjection {
  @Value("#{@userSecurity.canReadEmail(target) ? target.email: null}")
  String getEmail();
}

0
在数据访问层中添加Spring安全代码并不是一个好主意。我建议您将@PreAuthorize注释添加到控制器/服务方法中。由于您有一个查询参数?projection=details,因此可以为详细信息投影创建单独的控制器/服务方法。
请将以下内容添加到您的详细信息投影方法中:
@RequestMapping("/url", params = {"projection"})
@PreAuthorize("hasRole('LOGGED_IN') and principal.user.id == #id")

2
我对这种方法有一个问题,使用Spring Data Rest时,所有的控制器和服务都是由框架生成的,因此我只能处理存储库,从而可以配置安全性。我也有自定义URL,这个解决方案非常适合它。除非我完全错了,你能告诉我如何保护Spring Data Rest生成的URL(如/ users / {id}和/ users / {id} / userPosts),就像我在帖子中提到的那样,而不必在存储库中添加这些注释吗? - fortm
我还怀疑我是否可以将@RequestMapping添加到Spring数据Rest投影中? - fortm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接