在春季3.2.4中带有@RequestBody的@InitBinder转义XSS [英] @InitBinder with @RequestBody escaping XSS in Spring 3.2.4

查看:91
本文介绍了在春季3.2.4中带有@RequestBody的@InitBinder转义XSS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这样的方法中有一个 @RequestBody 注释的参数,如下所示:

I am having a @RequestBody annotated argument in my method like this:

@RequestMapping(value = "/courses/{courseId}/{name}/comment", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody CommentContainer addComment(@PathVariable Long courseId,
                          @ActiveAccount Account currentUser,
                          @Valid @RequestBody AddCommentForm form,
                          BindingResult formBinding,
                          HttpServletRequest request) throws RequestValidationException {

.....
}

然后我有一个在同一控制器中使用@InitBinder 注释的方法:

Then I have a @InitBinder annotated method in the same controller:

@InitBinder
public void initBinder(WebDataBinder dataBinder) {
    dataBinder.registerCustomEditor(AddCommentForm.class, new StringEscapeEditor());
}

我的 StringEscapeEditor 是没有运行。但是我的 initBinder 方法是。因此,它不会将我的表单映射到转义编辑器。读完此线程后,这似乎是正确的( @InitBinder 不支持 @RequestMapping ):

My StringEscapeEditor is not running. But my initBinder method is. So it does not mapping my form to the escape editor. This seems right after reading this thread (Where it seems like @RequestMapping is not supported by @InitBinder):

spring mvc @InitBinder在处理Ajax请求时未调用

我测试了映射 @PathVariable 字符串,然后我的编辑器正在工作。

And i tested to map a @PathVariable string and then my editor is working.

这在我的应用程序中很重要,因为大多数绑定都是通过 @RequestBody ,如果我可以对其应用一些自定义绑定,那就太好了。

This is a big deal in my application since most of my bindings is done with @RequestBody and it would be great if i could apply some custom bindings to it.

解决此问题的最常用方法是什么?

What is the most common way to solve this problem? and to escape my input data for script attacks.

推荐答案

为了逃避XSS,我建议在输出数据时进行转义,因为正确的转义取决于输出文档。

To escape XSS I suggest that escaping is done while outputting the data, because correct escaping depends on the output document.

如果 @ResponseBody 生成的JSON响应直接被客户端使用,则XSS没有机会逃避内容,然后可以自定义JacksonMessageConverter以对字符串执行XSS转义。

If JSON response generated by @ResponseBody is consumed directly by the client and there is no opportunity to XSS escape the content, then JacksonMessageConverter can be customised to perform XSS escaping on strings.

一个人可以自定义JacksonMessageConverter,如下所示:

One can customise JacksonMessageConverter like this:

1)首先,我们创建ObjectMapper工厂,该工厂将创建我们的自定义对象映射器:

1) First we create ObjectMapper factory that will create our custom object mapper:

public class HtmlEscapingObjectMapperFactory implements FactoryBean<ObjectMapper> {

    private final ObjectMapper objectMapper;

    public HtmlEscapingObjectMapperFactory() {
        objectMapper = new ObjectMapper();
        objectMapper.getJsonFactory().setCharacterEscapes(new HTMLCharacterEscapes());
    }

    @Override
    public ObjectMapper getObject() throws Exception {
        return objectMapper;
    }

    @Override
    public Class<?> getObjectType() {
        return ObjectMapper.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    public static class HTMLCharacterEscapes extends CharacterEscapes {

        private final int[] asciiEscapes;

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


        @Override
        public int[] getEscapeCodesForAscii() {
            return asciiEscapes;
        }

        // and this for others; we don't need anything special here
        @Override
        public SerializableString getEscapeSequence(int ch) {
            return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));

        }
    }
}

(HtmlCharacterEscapes的灵感来自于这个问题:使用Spring MVC和Jackson Mapper进行HTML转义

(inspiration for HtmlCharacterEscapes came from this question: HTML escape with Spring MVC and Jackson Mapper)

2)然后,我们注册使用自定义对象映射器的消息转换器(例如xml config中的示例):

2) Then we register the message converter that uses our custom object mapper (example in xml config):

<bean id="htmlEscapingObjectMapper" class="com.example.HtmlEscapingObjectMapperFactory" />

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" p:objectMapper-ref="htmlEscapingObjectMapper" />
    </mvc:message-converters>
</mvc:annotation-driven>

现在所有由 @ResponseBody 应该按照HTMLCharacterEscapes中的指定对字符串进行转义。

Now all the JSON messages created by @ResponseBody should have strings escaped as specified in HTMLCharacterEscapes.

该问题的替代解决方案:

Alternative solutions to the problem:


  • 在对象反序列化之后,XSS转义您在控制器主体中需要的内容

  • 也许在输出内容之前,在客户端上的javascript中使用XSS转义

除了进行转义输出外,还可以进行一些输入验证(使用标准的Spring验证方法)来阻止某些您不想要的内容,这可能是有用的

In addition to doing output escaping, it may be useful to also do some input validation (using standard Spring validation methods) to block some of the content that you don't want to be entered into the system / database.

编辑:JavaConfig

I还没有尝试过,但是在Java配置中应该像这样工作(您不需要上面的Factory Bean,因为在这种情况下可以在配置中设置所有内容):

I haven't tried this out but in Java config it should work like this (you won't need Factory Bean from above because you can set up everything in config in this case):

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    super.configureMessageConverters(converters);
    converters.add(buildHtmlEscapingJsonConverter());

}

private MappingJacksonHttpMessageConverter buildHtmlEscapingJsonConverter() {
    MappingJacksonHttpMessageConverter htmlEscapingConverter = new MappingJacksonHttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.getJsonFactory().setCharacterEscapes(new HTMLCharacterEscapes());
    htmlEscapingConverter.setObjectMapper(objectMapper);
    return htmlEscapingConverter;       
}

请注意,通常会是其他任何非json默认消息转换器现在配置已丢失(例如XML转换器等),并且如果需要它们,则需要手动添加它们(您可以在第2.2节中查看默认情况下处于活动状态的内容: http://www.baeldung.com/spring-httpmessageconverter-rest

Please be aware that any other non-json default message converters that would normally be configured will now be lost (e.g. XML converters etc..) and if you need them, you will need to add them manually (you can see what's active by default here in section 2.2: http://www.baeldung.com/spring-httpmessageconverter-rest)

这篇关于在春季3.2.4中带有@RequestBody的@InitBinder转义XSS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆