2017-02-28 18 views
2

我没有成功尝试有条件地和动态地选择哪个属性进行序列化以响应Jersey(使用Jackson)的每个请求。这背后的想法是安全地访问REST API中对象的属性。Jackson和Jersey的有条件地产序列号

我有几个对象在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但这是有条件的和动态的。我迄今发现的所有解决方案都是静态的。

这甚至可能吗?

+3

你看过'@ JsonView'吗? – dnault

回答

3

新泽西州有Entity Filtering支持。除了一般的过滤之外,它还支持Role-based Entity Filtering using (javax.annotation.security) annotations

所以,你可以使用@RolesAllowed@PermitAll@DenyAll注解域模型的属性

public static class Model { 
    private String secured; 

    @RolesAllowed({"ADMIN"}) 
    public String getSecured() { return this.secured; } 
} 

为了使这项工作,虽然,你需要设置的SecurityContext请求过滤器内。泽西将查找SecurityContext来验证角色。你可以在this post中看到更多关于它的信息(注意:实体过滤与该帖子中提到的任何真实授权是分开的,但是这篇文章解释了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以使其全部工作。

看到一个完整的测试用例this Gist

0

您可以注册自定义MessageBodyWriter https://jersey.java.net/documentation/latest/user-guide.html#d0e6951

的MessageBodyWriter会使用自定义的逻辑来决定写什么。

它可以用@JsonView完成,如@dnault所示。 http://www.baeldung.com/jackson-json-view-annotation

你MessageBodyWriter将举行杰克逊映射器,并在上面的链接描述你将应用writerWithView与匹配视图类。

编辑:看到这一个 - Jackson Json serialization: exclude property respect to the role of the logged user

相关问题