在春季3.2.4中带有@RequestBody的@InitBinder转义XSS

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

@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在同一个控制器中有一个带注释的方法:

@InitBinder

public void initBinder(WebDataBinder dataBinder) {

dataBinder.registerCustomEditor(AddCommentForm.class, new StringEscapeEditor());

}

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

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

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

解决此问题的最常用方法是什么?并转义我的输入数据以进行脚本攻击。

回答:

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

如果@ResponseBody客户端直接使用由生成的JSON响应,并且没有机会让XSS转义内容,那么可以自定义JacksonMessageConverter以对字符串执行XSS转义。

可以像这样自定义JacksonMessageConverter:

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

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转义)

2)然后,我们注册使用自定义对象映射器的消息转换器(例如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>

现在,由创建的所有JSON消息@ResponseBody都应具有HTMLCharacterEscapes中指定的转义字符串。

该问题的替代解决方案:

  • 对象反序列化后,XSS可以在控制器主体中逃脱所需的操作
  • 也许XSS在输出内容之前先在客户端的javascript中转义

除了进行输出转义之外,还可以进行一些输入验证(使用标准的Spring验证方法)来阻止一些您不想输入到系统/数据库中的内容,这可能是有用的。

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

@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)

以上是 在春季3.2.4中带有@RequestBody的@InitBinder转义XSS 的全部内容, 来源链接: utcz.com/qa/423112.html

回到顶部