[英]Conditional property serialization with Jackson and Jersey
我无法成功地尝试有条件地,动态地选择要序列化的属性,以响应使用Jersey的每个请求(使用Jackson)。 其背后的想法是安全地访问REST API中对象的属性。
我在API调用中返回了几个对象,这些对象应根据经过身份验证的用户显示/隐藏字段。
例如,假设我有一个对象Car
public class Car implements Serializable {
private Long id;
private String VIN;
private String color;
...
}
可以说,如果对具有ROLE_ADMIN
的用户进行了身份验证,则应该返回所有属性,但是如果没有登录的用户,则只需要显示前两个即可。
我在考虑构建基于注释的东西。 就像是:
public class Car implements Serializable {
private Long id;
private String VIN;
@Secured({AccessRole.ROLE_ADMIN})
private String color;
...
}
在这种情况下,仅当请求用户的访问角色与通过注释传递的访问角色匹配时,才应返回color
属性。
但是我无法确定应该在哪里实现此逻辑。
我正在尝试实现的是一种@JsonIgnore
但这是有条件且动态的。 到目前为止,我发现的所有解决方案都是静态的。
这有可能吗?
泽西岛支持实体过滤 。 除了常规过滤,它还支持使用(javax.annotation.security)批注的基于角色的实体过滤 。
因此,您可以在域模型属性上使用@RolesAllowed
, @PermitAll
和@DenyAll
批注
public static class Model {
private String secured;
@RolesAllowed({"ADMIN"})
public String getSecured() { return this.secured; }
}
但是,要使此工作有效,您需要在请求过滤器内设置SecurityContext
。 泽西岛将查找SecurityContext
来验证角色。 您可以在这篇文章中了解更多信息 (注意:实体过滤与该文章中提到的任何真实授权是分开的。但是该文章确实解释了SecurityContext)。
基本上,您将得到类似的信息(请注意,最后一行设置SecurityContext)。
@PreMatching
public static class SimpleAuthFilter implements ContainerRequestFilter {
private static final Map<String, User> userStore = new ConcurrentHashMap<>();
static {
userStore.put("peeskillet", new User("peeskillet", Arrays.asList("ADMIN", "USER")));
userStore.put("paulski", new User("paulski", Arrays.asList("USER")));
}
@Override
public void filter(ContainerRequestContext request) throws IOException {
final String authHeader = request.getHeaderString("Authorization");
final String username = authHeader.split("=")[1];
final User user = userStore.get(username);
if (user == null) {
throw new NotAuthorizedException("No good.");
}
request.setSecurityContext(new SimpleSecurityContext(user));
}
}
如果SimpleSecurityContext
只是您自己的一个类,则需要覆盖isUserInRole
方法并检查用户是否具有该角色
private static class SimpleSecurityContext implements SecurityContext {
private final User user;
SimpleSecurityContext(User user) {
this.user = user;
}
@Override
public Principal getUserPrincipal() {
return new Principal() {
@Override
public String getName() {
return user.getUsername();
}
};
}
@Override
public boolean isUserInRole(String role) {
return user.getRoles().contains(role);
}
@Override
public boolean isSecure() {
return false;
}
@Override
public String getAuthenticationScheme() {
return "simple";
}
}
就是这样。 您还需要在应用程序中注册SecurityEntityFilteringFeature
才能使其全部正常工作。
在此要点中查看完整的测试用例
您可以注册自定义MessageBodyWriter https://jersey.java.net/documentation/latest/user-guide.html#d0e6951
MessageBodyWriter将使用您的自定义逻辑来决定要写的内容。
可以按照@dnault建议使用@JsonView来完成。 http://www.baeldung.com/jackson-json-view-annotation
您的MessageBodyWriter将持有一个杰克逊映射器,并且您将按照上述链接中所述将writerWithView与匹配的视图类一起应用。
编辑:看到这一点- 杰克逊·杰森(Jackson Json)序列化:排除有关已登录用户角色的属性
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.