如何通过 Jackson 生成器生成 html 转义值

问题描述 投票:0回答:3

我们使用 Spring 及其内置的 MappingJacksonHttpMessageConverter 生成大量 JSON 对象。一切都很棒。

但现在我想html转义我的(任何类型)对象的字符串值,以防止XSS。

那么,我该如何解决这个问题呢?我首先想到我可以编写一个自定义对象映射器并将其放入 MappkingJacksonHttpMessageConverter 中。但是, writeValue 接受一个对象,而我不希望这样,我想要它的 fields 进行迭代。我打赌杰克逊转换器也需要这样做,而不是我自己这样做。所以我想影响那部分。

现在我最终得到了一个 SerializerProvider 接口。标准实现 (StdSerializerProvider) 由 ObjectMapper 调用。所以我想在某个地方覆盖/影响负责设置值的方法。

这可能吗?据我所知,很难扩展。我无法重写 StdSerializerProvider 来重写 ObjectMapper 使用的方法。也许我需要覆盖另一个?

或者,也许这是完全错误的,我需要从完全不同的角度来处理它?

有什么想法吗?

哦顺便说一句,我自己实现 SerializerProvider 并创建委托给 StdSerializerProvider 的组合可能是可能的,但我宁愿不这样做。 (我自己实例化 StdSerializerProvider 时已经遇到问题)。

任何想法表示赞赏!

java json spring spring-mvc jackson
3个回答
4
投票

有多种方法,具体取决于您如何识别您想要逃避的事物。一些想法:

  • 如果你想引用/转义所有字符串,你可以定义自定义字符串序列化器
  • 您可以先序列化为 JSON 树 (JsonNode) -- ObjectMapper.convertValue(pojo, JsonNode.class) -- 修改它,然后序列化为 JSON (ObjectMapper.writeValue(intermediateTree))
  • 如果您想要一个灵活的系统,可以为需要特殊处理的字段添加注释,您可以使用 ContextualSerializers 的 Jackson 1.7 功能;可以根据注释重新配置自身的自定义序列化器。乍一看,这似乎有些过头了,但这可以用来轻松指定自定义修饰符(值为 Class 的注释属性,指示序列化程序可以调用来修改正在序列化的值的对象——如转义)

1
投票

给出了这个答案,而问题是关于验证字符串不包含XSS并且不转义。如果您想转义字符串,这个答案对您没有帮助。

使用 JSR 303 Bean Validation 验证创建的对象(命令对象)怎么样?

例如,对“命令对象”的 String 属性使用 not @NotHtml(注释和验证)。

当然你必须自己实现@NotHtml(@NotJavaScript或@NotXSS)注释和验证器。


0
投票

您可以为此创建自定义

CharacterEscapes
实现:

// Custom CharacterEscapes implementation to treat HTML characters like GSON does by default
// (inspired by https://www.cowtowncoder.com/blog/archives/2012/08/entry_476.html)
private final static class HtmlCharacterEscapes extends CharacterEscapes {
    private final int[] asciiEscapes;

    public HtmlCharacterEscapes() {
        // start with set of characters known to require escaping (double-quote, backslash etc)
        int[] esc = CharacterEscapes.standardAsciiEscapesForJSON();
        // and force escaping of a few others:
        esc['<'] = CharacterEscapes.ESCAPE_STANDARD;
        esc['>'] = CharacterEscapes.ESCAPE_STANDARD;
        esc['&'] = CharacterEscapes.ESCAPE_STANDARD;
        esc['='] = CharacterEscapes.ESCAPE_STANDARD;
        esc['\''] = CharacterEscapes.ESCAPE_STANDARD;
        asciiEscapes = esc;
    }

    // this method gets called for character codes 0 - 127
    @Override public int[] getEscapeCodesForAscii() {
        return asciiEscapes;
    }

    // and this for others; we don't need anything special here
    @Override public SerializableString getEscapeSequence(int ch) {
        // no further escaping (beyond ASCII chars) needed:
        return null;
    }
}

我实际上在 StaxMan 的博客上找到了这个,所以我想知道为什么他们没有在答案中添加这个选项。

然后你有几个选项来注册它(

MAPPER_INSTANCE
将是静态/缓存的
JsonMapper
):

  1. 创建一个 HTML 转义 JSON writer 实例:

    ObjectWriter writer = MAPPER_INSTANCE.writer(new HtmlCharacterEscapes());.writer(new HtmlCharacterEscapes());
    
  2. 在映射器上全局注册它:

    MAPPER_INSTANCE.getFactory().setCharacterEscapes(new HtmlCharacterEscapes());
    
  3. 在Spring Boot中全局注册:

     @Bean
     public Jackson2ObjectMapperBuilder jacksonBuilder() {
         return new Jackson2ObjectMapperBuilder().factory(new JsonFactory().setCharacterEscapes(new HtmlCharacterEscapes()));
     }    
    
© www.soinside.com 2019 - 2024. All rights reserved.