2017-02-28 46 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

相關問題