You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非SpringBoot环境下Spring MVC4及JSON应用的XSS防护方案问询

Hey there, let's tackle your XSS protection questions for your vanilla Spring MVC 4 app (no Spring Boot) — I’ve got practical, framework-native solutions for both regular requests and raw JSON payloads:

1. XSS Protection for Standard Spring MVC 4 Requests

You don’t need Spring Boot-specific tools here; Spring MVC 4 has built-in hooks to intercept and sanitize input. Here are the most reliable approaches:

Option 1: Use a HandlerInterceptor with a Request Wrapper

Create an interceptor to wrap the request and sanitize all parameters before they reach your controllers:

First, the request wrapper that overrides parameter retrieval to clean values (using OWASP Java Encoder for safe HTML encoding):

public class XssRequestWrapper extends HttpServletRequestWrapper {
    public XssRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        return sanitize(value);
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values == null) return null;
        for (int i = 0; i < values.length; i++) {
            values[i] = sanitize(values[i]);
        }
        return values;
    }

    private String sanitize(String value) {
        return value != null ? Encoder.encodeForHtml(value) : null;
    }
}

Then the interceptor to apply this wrapper:

public class XssInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Replace original request with sanitized wrapper
        HttpServletRequest sanitizedRequest = new XssRequestWrapper(request);
        request = sanitizedRequest;
        return super.preHandle(sanitizedRequest, response, handler);
    }
}

Register the interceptor in your spring-servlet.xml:

<mvc:interceptors>
    <bean class="com.yourpackage.interceptors.XssInterceptor" />
</mvc:interceptors>

Option 2: Custom Property Editors for Controller Binding

If you want sanitization to happen automatically when binding request parameters to your model objects, use a @ControllerAdvice to register a custom property editor:

@ControllerAdvice
public class XssBindingAdvice {
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                // Sanitize string values before binding
                setValue(text != null ? Encoder.encodeForHtml(text) : null);
            }
        });
    }
}

Just make sure your component scan includes the package where this advice lives.

2. Global XSS Protection for Raw JSON Requests & Responses

Since you’re dealing with raw JSON (not form parameters), we need to hook into Spring’s JSON message conversion process. No JsonComponent (a Spring Boot feature) required — we’ll use Jackson’s native modules instead.

Step 1: Sanitize JSON Request Bodies

Create a custom Jackson deserializer for String fields that either sanitizes or blocks XSS content:

Option A: Sanitize Automatically

public class XssStringDeserializer extends StdDeserializer<String> {
    public XssStringDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String value = parser.getValueAsString();
        return value != null ? Encoder.encodeForHtml(value) : null;
    }
}

Option B: Throw Error on XSS Detection

If you want to reject requests with malicious content instead of sanitizing, use OWASP’s Validation library to check for XSS patterns:

public class XssBlockingDeserializer extends StdDeserializer<String> {
    private final Validator owaspValidator = new Validator();

    public XssBlockingDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String value = parser.getValueAsString();
        if (value != null && !owaspValidator.isValid(value, ValidationTarget.HTML)) {
            throw new IOException("Potential XSS content detected in request");
        }
        return value;
    }
}

Step 2: Sanitize JSON Responses

To protect your JSON output, create a corresponding serializer to encode string values:

public class XssStringSerializer extends StdSerializer<String> {
    public XssStringSerializer() {
        super(String.class);
    }

    @Override
    public void serialize(String value, JsonGenerator generator, SerializerProvider provider) throws IOException {
        if (value != null) {
            generator.writeString(Encoder.encodeForHtml(value));
        } else {
            generator.writeNull();
        }
    }
}

Step 3: Register the Jackson Module

Package the deserializer/serializer into a Jackson module and wire it into Spring’s message converter:

public class XssJacksonModule extends SimpleModule {
    public XssJacksonModule() {
        // Use XssBlockingDeserializer instead if you want to reject bad requests
        addDeserializer(String.class, new XssStringDeserializer());
        addSerializer(String.class, new XssStringSerializer());
    }
}

Update your spring-servlet.xml to use this custom module in the JSON converter:

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                    <property name="modules">
                        <list>
                            <bean class="com.yourpackage.jackson.XssJacksonModule" />
                        </list>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

This will apply XSS protection to all JSON request bodies and responses globally.

Alternative: Raw JSON Request Wrapper

If you prefer not to modify Jackson’s configuration, you can wrap the request to read and sanitize the entire JSON payload upfront:

public class XssJsonRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] sanitizedBody;

    public XssJsonRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        // Read original JSON body
        String originalBody = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        // Sanitize string values in JSON (use a proper JSON parser instead of regex for complex structures)
        String sanitizedBodyStr = originalBody.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
        sanitizedBody = sanitizedBodyStr.getBytes(request.getCharacterEncoding());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new ServletInputStream() {
            private final ByteArrayInputStream bis = new ByteArrayInputStream(sanitizedBody);

            @Override
            public int read() throws IOException {
                return bis.read();
            }

            @Override
            public boolean isFinished() {
                return bis.available() == 0;
            }

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

            @Override
            public void setReadListener(ReadListener listener) {}
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
    }
}

Then update your XssInterceptor to apply this wrapper to JSON requests:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String contentType = request.getContentType();
    if (contentType != null && contentType.contains("application/json")) {
        request = new XssJsonRequestWrapper(request);
    } else {
        request = new XssRequestWrapper(request);
    }
    return super.preHandle(request, response, handler);
}

Key Notes:

  • Always use trusted libraries like OWASP Java Encoder and OWASP Validation instead of writing your own regex — they cover edge cases you might miss.
  • For JSON, the Jackson module approach is more maintainable than raw string replacement, as it properly handles nested structures and string escaping.

内容的提问来源于stack exchange,提问作者Berlin Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:33:08