Requirement: Remove the leading and trailing spaces in the user form parameters due to the user's careless input to prevent business exceptions caused by the leading and trailing spaces
Implementation method 1: remove the leading and trailing spaces when the front-end parameters are passed in
Implementation method 2: The backend receives the parameters and processes the parameters, removes the spaces at the beginning and end of the parameters, and then does other services
Implementation method 3: Use Filter to process all requests, remove the spaces at the beginning and end of the request parameters and write them back
It is obvious that the code maintenance of implementation method 1 and implementation method 2 is serious, and it is necessary to manually remove the leading and trailing spaces for each parameter. Here we mainly talk about implementation method 3. The implementation method here uses the spring boot framework, which requires this framework or spring. There is a simple understanding, there is a project demo download address behind the article
1. Register the filter
/** * Remove the leading and trailing spaces filter of parameters * @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; }
2, ParamsFilter implements the Filter class
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() { } }
3. The ParameterRequestWrapper class is also the most important class to implement in this section. It inherits HttpServletRequestWrapper and rewrites its getParameter and getParameterValues methods. Another important thing is to rewrite the getInputStream method, because if the request starts with enctype=”application/x -www-form-urlencoded" method, getParameterMap can obtain the data submitted by the form, and if the request is submitted in the enctype="multipart/form-data" method, the data cannot be obtained. At this time, it must be obtained from the getInputStream stream. Get, the latter one is also a common type of post, which is why there is no parameter size limit for submitting requests with post . The specific code is as follows:
public class ParameterRequestWrapper extends HttpServletRequestWrapper { private Map<String , String[]> params = new HashMap<String, String[]>(); public ParameterRequestWrapper(HttpServletRequest request) { // Give the request to the parent class, so that when the corresponding method is called, it will be output. In fact, the implementation method of the parent class is similar to the first new method. super(request); //Assign the parameter list to the current Map in order to hold the parameters in the request Map<String, String[]> requestMap=request.getParameterMap(); System.out.println("Parameter before conversion: "+JSON.toJSONString(requestMap)); this.params.putAll(requestMap); this.modifyParameterValues(); System.out.println("Converted parameters: "+JSON.toJSONString(params)); } /** * Rewrite the getInputStream method post type request parameters must pass through the stream to get the value */ @Override public ServletInputStream getInputStream() throws IOException { //Non-json type, return directly if(!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)){ return super.getInputStream(); } // empty, return directly String json = IOUtils.toString(super.getInputStream(), "utf-8"); if (StringUtils.isEmpty(json)) { return super.getInputStream(); } System.out.println("Parameter before conversion: "+json); Map<String,Object> map=StringJsonUtils.jsonStringToMap(json); System.out.println("Converted parameters: "+JSON.toJSONString(map)); ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes("utf-8")); return new MyServletInputStream(bis); } /** * Rewrite the value of parameter after removing spaces */ public void modifyParameterValues(){ Set<String> set =params.keySet(); Iterator<String> it=set.iterator(); while(it.hasNext()){ String key= (String) it.next(); String[] values = params.get(key); values[0] = values[0].trim(); params.put(key, values); } } /** * Rewrite the getParameter parameter to get from the map in the current class */ @Override public String getParameter(String name) { String[]values = params.get(name); if(values == null || values.length == 0) { return null; } return values[0]; } /** * Override getParameterValues */ public String[] getParameterValues(String name) {//同上 return params.get(name); } class MyServletInputStream extends ServletInputStream{ private ByteArrayInputStream bis; public MyServletInputStream(ByteArrayInputStream bis){ this.until=until; } @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(); } } }
4. Start the project access: http://localhost/test/get?userName=%20%20%20dd%20%20
The result is as follows:
Reserve a question: how to achieve XSS attack through filter?
PS: Download the complete project path of this demo project: https://github.com/zqh1989/spring/tree/master/spring-boot-filter-01