项目中如何对XSS统一处理
XSS攻击是什么?
XSS攻击是指攻击者利用网站中的漏洞,向页面中注入恶意脚本,从而获取用户的信息或者控制用户的计算机。 举一个通俗的例子,早期使用JSP页面渲染页面的项目,如果将用户名改成nick<alert>1</alert>,则当用户打开页面时,就会弹出一个警告框,而这个警告框可以被恶意脚本所替代,例如读取cookies或者其他敏感信息等操作。
如何在项目中防范XSS攻击呢
有一些项目使用Filter+注解的方式来过滤或者提示XSS攻击。 通过在参数中的字段上加上类似@Xss的注解,来表示这个字段是不允许输入XSS脚本的。 但是这种实现我觉得有几点不便之处。
-
严格来说,其实普通系统内的绝大部分输入字段都不允许输入XSS文本。除非一些存储富文本的字段。因此需要在很多字段上去标注上@Xss注解。 Filter中的代码,需要重复去读Request类的数据,因此需要自己实现一个可重复读的RequestWrapper.
因此我使用了JsonDeserializer更简单的处理全局的防Xss处理。
原理
Jackson框架允许自定义JsonDeserializer,因此可以在自定义的JsonDeserializer中剔除恶意XSS脚本注入。
自定义Xss过滤序列化器
/** * 直接将html标签去掉 * @author valarchie */ public class JsonHtmlXssTrimSerializer extends JsonDeserializer<String> { public JsonHtmlXssTrimSerializer() { super(); } @Override public String deserialize(JsonParser p, DeserializationContext context) throws IOException { String value = p.getValueAsString(); if( value != null) { // 去除掉html标签 如果想要转义的话 可使用 HtmlUtil.escape() return HtmlUtil.cleanHtmlTag(value); } return null; } @Override public Class<String> handledType() { return String.class; } }
配置自定义Xss过滤序列化器
@Configuration public class JacksonConfig implements Jackson2ObjectMapperBuilderCustomizer{ @Override public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { // 防XSS脚本注入 jacksonObjectMapperBuilder.deserializers(new JsonHtmlXssTrimSerializer()); } }
如何支持富文本
某一些字段可能是需要支持富文本的,比如公告栏里的内容之类的。此时我们可以给特定的字段标注标准的JsonDeserializer来覆盖我们自定义的序列化器。 以下是例子。
/** * @author valarchie */ @Data public class NoticeAddCommand { /** * 想要支持富文本的话, 避免Xss过滤的话, 请加上@JsonDeserialize(using = StringDeserializer.class) 注解 */ @NotBlank @JsonDeserialize(using = StringDeserializer.class) protected String noticeContent; protected String status; }