Java 如何按角色限制对Spring数据REST投影的访问?
在使用Spring数据JPA和Spring数据REST的应用程序中,假设您有这样一个实体类:Java 如何按角色限制对Spring数据REST投影的访问?,java,spring,rest,spring-data,spring-data-rest,Java,Spring,Rest,Spring Data,Spring Data Rest,在使用Spring数据JPA和Spring数据REST的应用程序中,假设您有这样一个实体类: @Entity public class Person { @Id @GeneratedValue private int id; private String name; @JsonIgnore private String superSecretValue; ... } curl http://localhost:8080/persons?projec
@Entity
public class Person {
@Id @GeneratedValue
private int id;
private String name;
@JsonIgnore
private String superSecretValue;
...
}
curl http://localhost:8080/persons?projection=withSecret
我们希望SpringDataREST公开该实体的所有字段,除了superSecretValue
,因此我们用@JsonIgnore
注释了该字段
但是,在某些情况下,我们确实希望访问superSecretValue
,因此我们创建了一个投影,该投影将返回所有字段,包括该字段:
@Projection(name = "withSecret", types = {Person.class})
public interface PersonWithSecret {
String getName();
String getSuperSecretValue();
}
太棒了。现在我们可以访问Person
实体,包括superSecretValue
字段,如下所示:
@Entity
public class Person {
@Id @GeneratedValue
private int id;
private String name;
@JsonIgnore
private String superSecretValue;
...
}
curl http://localhost:8080/persons?projection=withSecret
我的问题是我们如何确保该投影?我们如何配置事物,使任何人都可以检索Person
实体,而无需superSecretValue
字段。。。但是只有具有特定角色的人(例如,role\u ADMIN
)才能使用投影来检索隐藏字段
我发现了无数使用
@PreAuthorize
或@Secured
注释来保护Spring数据JPA存储库CRUD方法的例子(例如save()
,delete()
)。。。但是没有关于如何限制Spring数据REST投影使用的示例。您可以使用带有条件SpEL表达式的@Value
在投影中重载属性,如下所示
考虑其他备选方案(已提及的其他方案):
人
账户
)资源
类型(DTO)(例如,返回公共人员
,而不是人员
)。然后,您可以编写自定义资源处理器,以便为这些类型添加自定义链接和自定义投影另请参阅:spring data rest中关于此主题的问题。您可以尝试以下解决方案:
以前有人问过这个问题——我认为你试图做的事不受支持。此外,我想问你是否应该这样做——预测只是对数据的不同看法,在这里引入安全性听起来并不正确。我将为此实现一个自定义控制器方法并保护此方法。@MathiasdPunk:假设您确实编写了一个自定义控制器方法。。。返回类型为
Person
,并应用@ResponseBody
注释将其序列化为JSON。在这种情况下,由于@JsonIgnore
注释,仍将省略superSecretValue
字段。那么,您是否可以手动将Person
实体转换为基本相同的DTO类,而该字段上没有@JsonIgnore
?您是否会实现自己的定制Jackson序列化程序,并自行构建JSON,而不是依赖@ResponseBody
?另一种方法?@MathiasDpunkt:似乎它必须是一个不太常见的用例,才能在某些字段上需要基于角色的可见性。授予对存储库CRUD方法的基于角色的访问是如此简单,授予实体字段的基于角色的可见性是如此繁琐,这相当奇怪。只是想找出阻力最小的途径。别误会我-我不认为你的要求有什么问题。但我认为,你尝试建模的方式可能需要一些考虑。如果superSecretValue
在安全性方面与其他person属性不同,那么它可能根本不属于该person。如果将此值建模为一个单独的实体,该怎么办。然后,您可以提供一个单独的存储库,其中包含适当的授权规则,只有授权用户才能遍历从person到secret值的关系。具有不同访问级别的@OneToOne
代理实体。这不是100%的理想,但可以完成工作。