To remove XSS strings, you need to use the utility class Jsoup, which is a bit too powerful. Jsoup can filter out XSS attacks directly, and also escape the Angle brackets <>. > , stored in the library is the escaped string. It needs to be rotated when it comes out.

12<>3455

[12 lt; > 3455] [12 lt; > 3455]

If the above results are acceptable, then the utility class can be used.

Introduce dependency jsoup

<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.12.1</version>Copy the code

Jsouputil.java utility class:


import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;

/ * * * *@Auther linmengmeng
 * @Date 2021-08-19 15:47 * * Description: Filter XSS code in HTML tags */
public class JsoupUtil {
    /** * Use the built-in basicWithImages whitelist * A, b, blockquote, br, cite, code, dd, dl, dt, em, I, li, ol, p, the pre, q, small, span, strike, strong, sub, sup, u, ul, img * and a href tag, img Label of SRC, align, Alt, height, width, the title attribute * /
    private static final Whitelist whitelist = Whitelist.basicWithImages();
    /** Configures filter parameters without formatting code */
    private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
    static {
        // Some styles are implemented using style in rich text editing
        Style ="color:red;"
        // Add a style attribute to all tags
        whitelist.addAttributes(":all"."style");
    }
    public static String clean(String content) {
        return Jsoup.clean(content, "", whitelist, outputSettings); }}Copy the code

The first step is to define a parameter Filter: ParamsFilter implements the Filter class

import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * Description : * */ public class ParamsFilter implements Filter {@override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { ParameterRequestWrapper parmsRequest = new ParameterRequestWrapper( (HttpServletRequest) arg0); arg2.doFilter(parmsRequest, arg1); } @Override public void init(FilterConfig arg0) throws ServletException { } @Override public void destroy() { } }Copy the code

Add a parameter filtering profile:

import gc.cnnvd.framework.core.filter.ParamsFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.DispatcherType; @configuration public class ParameterTrimConfig {@return */ @bean public FilterRegistrationBean parmsFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setDispatcherTypes(DispatcherType.REQUEST); registration.setFilter(new ParamsFilter()); registration.addUrlPatterns("/*"); registration.setName("paramsFilter"); registration.setOrder(Integer.MAX_VALUE-1); return registration; }}Copy the code

It’s all been handed over to this guy:

import com.alibaba.fastjson.JSON; import gc.cnnvd.framework.config.converter.JsonValueTrimUtil; import gc.cnnvd.framework.util.JsoupUtil; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** ** @auther linmengmeng * @date 2021-03-25 15:47 ** Description: Request parameters processing, * 1. Remove space before and after the parameter * 2. XSS filtering illegal characters * * / public class ParameterRequestWrapper extends HttpServletRequestWrapper {private Map < String  , String[]> params = new HashMap<>(); Public ParameterRequestWrapper(HttpServletRequest Request) {// Give the request to the parent class so that it can be output when the corresponding method is called. In fact, the implementation of the parent class is similar to the first new method super(request); RequestMap <String, String[]> requestMap= request.getparameterMap (); this.params.putAll(requestMap); this.modifyParameterValues(); } /** * Override public ServletInputStream getInputStream() throws getInputStream() IOException {// non-json, returns if (! MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){ return super.getInputStream(); } // empty, return String json = ioutils.toString (super.getinputStream (), standardCharsets.utf_8); if (StringUtils.isEmpty(json)) { return super.getInputStream(); } Object resultObject = JsonValueTrimUtil.jsonStrTrim(json); ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(resultObject).getBytes(StandardCharsets.UTF_8)); return new CustomServletInputStream(bis); } /** * public void modifyParameterValues(){Set<String> Set = params.keySet(); Iterator<String> it = set.iterator(); while(it.hasNext()){ String key = it.next(); String[] values = params.get(key); values[0] = values[0].trim(); values[0] = JsoupUtil.clean(values[0]); // Params. Put (key, values); Override public String getParameter(String name) {String[]values = params.get(name); if(values == null || values.length == 0) { return null; } return values[0]; } /** * Override public String[] getParameterValues(String name) {return params.get(name);  } class CustomServletInputStream extends ServletInputStream{ private ByteArrayInputStream bis; public CustomServletInputStream(ByteArrayInputStream bis){ this.bis=bis; } @Override public boolean isFinished() { return true; } @Override public boolean isReady() { return true; } @Override public void setReadListener(ReadListener listener) { } @Override public int read() throws IOException { return bis.read(); }}}Copy the code

JSON () {JSON () {JSON () {JSON () {JSON ();}}

import cn.hutool.json.JSONTokener; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import gc.cnnvd.framework.util.JsoupUtil; import org.apache.commons.lang3.StringUtils; import java.util.Map; import java.util.Set; /** * @Auther linmengmeng * @Date 2021-03-25 15:47 * 1. 2. Remove XSS attack character */ public class JsonValueTrimUtil {public static Object jsonStrTrim(String jsonStr){ if (StringUtils.isBlank(jsonStr)){ return ""; } Object typeObject = new JSONTokener(jsonStr).nextValue(); if (typeObject instanceof cn.hutool.json.JSONObject){ return jsonObjectTrim(JSONObject.parseObject(jsonStr)); } if (typeObject instanceof cn.hutool.json.JSONArray){ return jsonArrayTrim(JSONArray.parseArray(jsonStr)); } jsonStr = JsoupUtil.clean(jsonStr); return jsonStr.trim(); } /** * @Description: @param jsonObject @return */ public static jsonObject jsonObjectTrim(jsonObject jsonObject){// Set< map.entry <String, Object>> entrySets = jsonObject.entrySet(); entrySets.forEach(entry -> { Object value = entry.getValue(); if (value == null){ return; } if (value instanceof String) { String resultValue = (String) value; if (StringUtils.isNotBlank(resultValue)){ resultValue = resultValue.trim(); resultValue = JsoupUtil.clean(resultValue); jsonObject.put(entry.getKey(), resultValue); } return; } if (value instanceof JSONObject){ jsonObject.put(entry.getKey(), jsonObjectTrim((JSONObject) value)); return; } if (value instanceof JSONArray){ jsonObject.put(entry.getKey(), jsonArrayTrim((JSONArray) value)); return; }}); return jsonObject; } /** * @Description: * @param arr * @return */ public static JSONArray jsonArrayTrim(JSONArray arr){ if( arr ! = null && arr.size() > 0){ Object tempObject = null; for (int i = 0; i < arr.size(); i++) { tempObject = arr.get(i); if (tempObject instanceof String){ arr.set(i, tempObject ); continue; } JSONObject jsonObject = (JSONObject) arr.get(i); JsonObject = jsonObjectTrim(jsonObject); arr.set(i, jsonObject ); } } return arr; }}Copy the code

Test it out:

import gc.cnnvd.framework.common.api.ApiResult; import gc.cnnvd.framework.log.annotation.OperationLogIgnore; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiOperation; import lombok.Data; import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.constraints.NotBlank; import java.io.Serializable; /** * @Auther linmengmeng * @Date 2021-03-30 16:24 */ @Slf4j @RestController @RequestMapping("/tourist") @Api(value = "Test visitor page XSS ", Tags = {" visitor page XSS "}) public class TouristTestXssController {@postMapping ("/testXssForm") @OperationLogignore @apiOperation (value = "xssForm", notes =" xssForm", response = String.class) public ApiResult<String> testXss(TestXssFormParam testXssFormParam) { log.info("form param testStr:[{}]", testXssFormParam.getTestStr()); / / the from a bad return ApiResult. Ok (testXssFormParam. GetTestStr ()); } @postmapping ("/testXssJson") @operationLogignore @APIOperation (value = "test open visitor page interface xssJson", Notes = "Test open visitor page interface xssJson", response = String.class) public ApiResult<String> testXssJson(@Validated @RequestBody TestXssFormParam testXssFormParam)  { log.info("json param testStr:[{}]", testXssFormParam.getTestStr()); return ApiResult.ok(testXssFormParam.getTestStr()); } @data @accessors (chain = true) @apiModel (value = "testXss parameter ") public static class TestXssFormParam implements Serializable { private static final long serialVersionUID = 1L; @notBlank (message = "testStr cannot be empty ") @APIModelProperty ("testStr") private String testStr; }}Copy the code

The ApiResult is a custom encapsulation of the return data format, you can directly modify the interface return type to String, just to see what the background processing, return to the foreground.

The filter succeeded. Procedure

JSON parameter, also fine.