使用@RolesAllowed 通过 RESTEasy 和 Jackson 过滤实体属性
Using @RolesAllowed to filter entity properties with RESTEasy and Jackson
使用 RESTEasy 和 Jackson,是否可以在我的模型中使用 @RolesAllowed
注释,以避免某些属性在输出中被序列化,具体取决于用户的角色?
我已经找到了大量关于如何使用 Jersey 执行此操作的文档,但没有找到关于 RESTEasy 的文档。
我在这个架构上受阻,所以切换库不是一个选项,使用自定义 ObjectMapper
解释 here 也不是一个选项,因为模型足够大标记大型数据集的每个 属性 以进行正确序列化太耗时了。另外,这是指 Jackson 库的旧版本,我不确定如何使其与新版本一起使用。
编辑
具体请参阅 this blog post 以了解我要完成的工作。请注意,这是 Jersey 特有的,到目前为止我没有找到关于 RESTEasy 的文档来完成这个。
如果你不愿意使用@JsonView
, you could consider @JsonFilter
. You first need to extend SimpleBeanPropertyFilter
并根据用户角色控制序列化:
public class RoleBasedPropertyFilter extends SimpleBeanPropertyFilter {
private String allowedRole;
public RoleBasedPropertyFilter(String allowedRole) {
this.allowedRole = allowedRole;
}
@Override
public void serializeAsField(Object pojo, JsonGenerator jgen,
SerializerProvider provider,
PropertyWriter writer) throws Exception {
PermitAll permitAll = writer.getAnnotation(PermitAll.class);
if (permitAll != null) {
serializeAsField(pojo, jgen, provider, writer);
return;
}
DenyAll denyAll = writer.getAnnotation(DenyAll.class);
if (denyAll != null) {
writer.serializeAsOmittedField(pojo, jgen, provider);
return;
}
RolesAllowed rolesAllowed = writer.getAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
if (!Arrays.asList(rolesAllowed.value()).contains(allowedRole)) {
writer.serializeAsOmittedField(pojo, jgen, provider);
return;
}
}
// If no annotation is provided, the property will be serialized
writer.serializeAsField(pojo, jgen, provider);
}
}
要将过滤器应用于某个 bean,请使用 @JsonFilter("roleBasedPropertyFilter")
:
对其进行注释
@JsonFilter("roleBasedPropertyFilter")
public class User {
private String firstName;
private String lastName;
private String email;
private String password;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@RolesAllowed({"ADMIN"})
public String getEmail() {
return email;
}
@DenyAll
public String getPassword() {
return password;
}
// Other getters and setters
}
然后在 ContextResolver
for ObjectMapper
:
中注册您的过滤器
String currentUserRole = // Get role from the current user
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("roleBasedPropertyFilter",
new RoleBasedPropertyFilter(currentUserRole));
ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);
如果你想使你的过滤器"global",即应用于所有bean,你可以创建一个mix-in class并用@JsonFilter("roleBasedPropertyFilter")
注释它:
@JsonFilter("roleBasedPropertyFilter")
public class RoleBasedPropertyFilterMixIn {
}
然后将混音 class 绑定到 Object
:
mapper.addMixIn(Object.class, RoleBasedPropertyFilterMixIn.class);
使用 RESTEasy 和 Jackson,是否可以在我的模型中使用 @RolesAllowed
注释,以避免某些属性在输出中被序列化,具体取决于用户的角色?
我已经找到了大量关于如何使用 Jersey 执行此操作的文档,但没有找到关于 RESTEasy 的文档。
我在这个架构上受阻,所以切换库不是一个选项,使用自定义 ObjectMapper
解释 here 也不是一个选项,因为模型足够大标记大型数据集的每个 属性 以进行正确序列化太耗时了。另外,这是指 Jackson 库的旧版本,我不确定如何使其与新版本一起使用。
编辑
具体请参阅 this blog post 以了解我要完成的工作。请注意,这是 Jersey 特有的,到目前为止我没有找到关于 RESTEasy 的文档来完成这个。
如果你不愿意使用@JsonView
, you could consider @JsonFilter
. You first need to extend SimpleBeanPropertyFilter
并根据用户角色控制序列化:
public class RoleBasedPropertyFilter extends SimpleBeanPropertyFilter {
private String allowedRole;
public RoleBasedPropertyFilter(String allowedRole) {
this.allowedRole = allowedRole;
}
@Override
public void serializeAsField(Object pojo, JsonGenerator jgen,
SerializerProvider provider,
PropertyWriter writer) throws Exception {
PermitAll permitAll = writer.getAnnotation(PermitAll.class);
if (permitAll != null) {
serializeAsField(pojo, jgen, provider, writer);
return;
}
DenyAll denyAll = writer.getAnnotation(DenyAll.class);
if (denyAll != null) {
writer.serializeAsOmittedField(pojo, jgen, provider);
return;
}
RolesAllowed rolesAllowed = writer.getAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
if (!Arrays.asList(rolesAllowed.value()).contains(allowedRole)) {
writer.serializeAsOmittedField(pojo, jgen, provider);
return;
}
}
// If no annotation is provided, the property will be serialized
writer.serializeAsField(pojo, jgen, provider);
}
}
要将过滤器应用于某个 bean,请使用 @JsonFilter("roleBasedPropertyFilter")
:
@JsonFilter("roleBasedPropertyFilter")
public class User {
private String firstName;
private String lastName;
private String email;
private String password;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@RolesAllowed({"ADMIN"})
public String getEmail() {
return email;
}
@DenyAll
public String getPassword() {
return password;
}
// Other getters and setters
}
然后在 ContextResolver
for ObjectMapper
:
String currentUserRole = // Get role from the current user
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("roleBasedPropertyFilter",
new RoleBasedPropertyFilter(currentUserRole));
ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);
如果你想使你的过滤器"global",即应用于所有bean,你可以创建一个mix-in class并用@JsonFilter("roleBasedPropertyFilter")
注释它:
@JsonFilter("roleBasedPropertyFilter")
public class RoleBasedPropertyFilterMixIn {
}
然后将混音 class 绑定到 Object
:
mapper.addMixIn(Object.class, RoleBasedPropertyFilterMixIn.class);