根据用户角色反序列化JSON字段

时间:2016-04-17 10:54:50

标签: spring jackson

我在模型中有一些字段,我只希望在登录用户具有角色 function Person(){} Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ }; var person1 = new Person(); person1.hasOwnProperty("name") // false ? 时返回该字段。我可以使用person1.hasOwnProperty("name") // is true但是它会为每个人隐藏它。如何让它动态隐藏?

2 个答案:

答案 0 :(得分:2)

您应该使用Jackson Json Views技术来实现它 - 它允许选择以编程方式序列化的不同字段集。它也受Spring

支持

考虑您有一个类Model,其中包含两个属性:commonField应该适用于所有人,secretField应该只适用于某些用户。您应该创建一个视图层次结构(任何类都可以工作)并使用@JsonView注释指定哪个视图在哪个视图中可用

package com.stackoverflow.jsonview;

import com.fasterxml.jackson.annotation.JsonView;

public class Model {

    public static class Public {}
    public static class Secret extends Public {}

    @JsonView(Public.class)
    private String commonField;

    @JsonView(Secret.class)
    private String secretField;

    public Model() {
    }

    public Model(String commonField, String secretField) {
        this.commonField = commonField;
        this.secretField = secretField;
    }

    public String getCommonField() {
        return commonField;
    }

    public void setCommonField(String commonField) {
        this.commonField = commonField;
    }

    public String getSecretField() {
        return secretField;
    }

    public void setSecretField(String secretField) {
        this.secretField = secretField;
    }

}

现在,您可以在具体的ObjectMapper

中指定要使用的视图
package com.stackoverflow.jsonview;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;

import static org.junit.Assert.*;

/**
 */
public class ModelTest {

    @Test
    public void testSecretField() throws JsonProcessingException {
        Model model = new Model("commonField","secretField");
        assertEquals("{\"commonField\":\"commonField\",\"secretField\":\"secretField\"}", new ObjectMapper().writerWithView(Model.Secret.class).writeValueAsString(model));
        assertEquals("{\"commonField\":\"commonField\"}", new ObjectMapper().writerWithView(Model.Public.class).writeValueAsString(model));
    }

}

我不确定你是否可以使用declaratie方法让spring根据开箱即用的用户角色选择正确的视图,所以你可能需要写一些这样的代码:

@RequestMapping("/data")
public String getData(HttpServletRequest request) {
    Model model = service.getModel();
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper = request.isUserInRole("ROLE_ADMIN") ? objectMapper.writerWithView(Model.Secret.class) : objectMapper.writerWithView(Model.Public.class);
    return objectMapper.writeValueAsString(model);
}

答案 1 :(得分:1)

经过整整一个月的尝试,我解决了这个问题。我正在使用Spring 4.3.1并启动,使用pagedrepository在Hal中返回数据。

  1. RepositoryRestMvcConfiguration扩展为MyRepositoryRestMvcConfiguration并将@Configuration添加到班级,确保您的入门班级有@EnableWebMvc

  2. 将此内容添加到MyRepositoryRestMvcConfiguration - 将TypeConstrainedMappingJackson2HttpMessageConverter扩展为MyResourceSupportHttpMessageConverter

  3. 将此内容添加到MyRepositoryRestMvcConfiguration

    @Override
    @Bean
    public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter() {
    
    ArrayList<MediaType> mediaTypes = new ArrayList<MediaType>();
    mediaTypes.add(MediaTypes.HAL_JSON);
    
    if (config().useHalAsDefaultJsonMediaType()) {
        mediaTypes.add(MediaType.APPLICATION_JSON);
    }
    
    int order = config().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10
            : Ordered.LOWEST_PRECEDENCE - 1;
    
    TypeConstrainedMappingJackson2HttpMessageConverter converter = new MyResourceSupportHttpMessageConverter(
            order);
    converter.setObjectMapper(halObjectMapper());
    converter.setSupportedMediaTypes(mediaTypes);
    
    converter.getObjectMapper().addMixIn(Object.class, MyFilteringMixin.class);
    final FilterProvider myRestrictionFilterProvider = new SimpleFilterProvider()
            .addFilter("MyFilteringMixin", new MyPropertyFilter()).setFailOnUnknownId(false);
    converter.getObjectMapper().setFilterProvider(myRestrictionFilterProvider);
    
    return converter;
    }
    
  4. 创建一个空的Mixin

    package filters;
    import com.fasterxml.jackson.annotation.JsonFilter;
    @JsonFilter("MyFilteringMixin")
    public class MyFilteringMixin {}
    
  5. 创建一个空的Mixin 创建扩展MyPropertyFilter的类SimpleBeanPropertyFilter并覆盖适应此方法 serializeAsField(Object, JsonGenerator, SerializerProvider, PropertyWriter)您需要调用super.serializeAsField(pPojo, pJgen, pProvider, pWriter)pWriter.serializeAsOmittedField(pPojo, pJgen, pProvider),具体取决于您是希望包含还是放弃此特定字段。

  6. 我在我想要改变的特定字段中添加了一个注释,并在决定调用这两个中的哪一个时查询该注释。我在注释中注入了安全角色并存储了允许的角色。

    这改变了Hal与调用者共享的内容,而不是Hal在其存储库中持有的内容。因此,您可以根据呼叫者的身份对其进行变形。