Filter拦截过滤参数
- Filter拦截过滤参数 推荐度:
- 相关推荐
Filter拦截过滤参数
来自连接SpringBoot过滤器(过滤请求参数) - 简书
获取http参数有两种方式,一种通过request.getParameter获取Get方式传递的参数,另外一种是通过request.getInputStream或reques.getReader获取通过POST/PUT/DELETE/PATCH传递的参数;
- @PathVariable注解是REST风格url获取参数的方式,只能用在GET请求类型,通过getParameter获取参数
- @RequestParam注解支持GET和POST/PUT/DELETE/PATCH方式,Get方式通过getParameter获取参数和post方式通过getInputStream或getReader获取参数
- @RequestBody注解支持POST/PUT/DELETE/PATCH,可以通过getInputStream和getReader获取参数
- HttpServletRequest参数可以通过getParameter和getInputStream或getReader获取参数
上述通过getInputStream或getReader在拦截器中获取会导致控制器拿到的参数为空,这是因为流读取一次之后流的标志位已经发生了变化,无法多次读取参数;
通过HttpServletRequestWrapper包装类每次读取参数后再回写参数
-
创建ParamsFilter实现Filter接口
package com.example.filter;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;/*** * @description: 请求参数过滤器* */
public class ParamsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;ParamsRequestWrapper requestWrapper = new ParamsRequestWrapper(httpRequest);filterChain.doFilter(requestWrapper, servletResponse);}@Overridepublic void destroy() {}}
-
过滤请求参数
-
package com.example.filter;import com.alibaba.fastjson.JSON; 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.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set;/*** * @description: 对请求参数进行过滤* */ public class ParamsRequestWrapper extends HttpServletRequestWrapper {private Map<String, String[]> params = new HashMap<>();private static final String ENCODING = "UTF-8";private static final String CLASSTYPE = "java.lang.String";public ParamsRequestWrapper(HttpServletRequest request) {super(request);// 将参数表,赋予给当前的Map以便于持有request中的参数Map<String, String[]> requestMap = request.getParameterMap();System.out.println("转化前参数:" + JSON.toJSONString(requestMap));this.params.putAll(requestMap);this.modifyParameters();System.out.println("转化后参数:" + JSON.toJSONString(params));}/*** 重写getInputStream方法 post请求参数必须通过流才能获取到值*/@Overridepublic ServletInputStream getInputStream() throws IOException {ServletInputStream stream = super.getInputStream();//非json类型,直接返回if (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) {return stream;}String json = IOUtils.toString(stream, ENCODING);if (StringUtils.isBlank(json)) {return stream;}System.out.println("转化前参数:" + json);Map<String, Object> map = modifyParams(json);System.out.println("转化后参数:" + JSON.toJSONString(map));ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes(ENCODING));return new ParamsServletInputStream(bis);}private static Map<String, Object> modifyParams(String json) {Map<String, Object> params = JSON.parseObject(json);Map<String, Object> maps = new HashMap<>(params.size());for (String key : params.keySet()) {Object value = getValue(params.get(key));maps.put(key, value);}return maps;}private static Object getValue(Object obj) {if (obj == null) {return null;}String type = obj.getClass().getName();// 对字符串的处理if (CLASSTYPE.equals(type)) {obj = obj.toString().trim();}return obj;}/*** 将parameter的值去除空格后重写回去*/private void modifyParameters() {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);}}/*** 重写getParameter 参数从当前类中的map获取*/@Overridepublic String getParameter(String name) {String[] values = params.get(name);if (values == null || values.length == 0) {return null;}return values[0];}}
-
字节数据转换流(Map → ByteArrayInputStream → ServletInputStream )
package com.example.filter;import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;/*** * @description: 请求参数输入流* */
public class ParamsServletInputStream extends ServletInputStream {private ByteArrayInputStream bis;public ParamsServletInputStream(ByteArrayInputStream bis) {this.bis = bis;}@Overridepublic boolean isFinished() {return true;}@Overridepublic boolean isReady() {return true;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() throws IOException {return bis.read();}}
- 过滤器配置类
package com.example.config;import com.example.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;/*** @description: 过滤器配置类*/
@Configuration
public class FilterConfig {@Beanpublic 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;}}
过滤器过滤的请求为所有请求(/*),排除部分请求
-
在配置类中添加不需要过滤的请求的url
package com.example.config;import com.example.filter.ParamsFilter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.servlet.DispatcherType;
import java.util.HashSet;
import java.util.Set;/*** @description: 过滤器配置类*/
@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean parmsFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setDispatcherTypes(DispatcherType.REQUEST);registration.setFilter(new ParamsFilter());registration.addUrlPatterns("/*");// 排除不需要过滤的请求Set<String> set = new HashSet<>();set.add("/hello");set.add("/testFilter");String urls = StringUtils.join(set.toArray(), ",");registration.addInitParameter("exclusions", urls);registration.setName("ParamsFilter");registration.setOrder(Integer.MAX_VALUE - 1);return registration;}}
package com.example.filter;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;/*** @description: 请求参数过滤器*/
public class ParamsFilter implements Filter {public static final String PARAM_NAME_EXCLUSIONS = "exclusions";public static final String SEPARATOR = ",";private Set<String> excludesUrls;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {String param = filterConfig.getInitParameter(PARAM_NAME_EXCLUSIONS);if (param != null && param.trim().length() != 0) {this.excludesUrls = new HashSet(Arrays.asList(param.split(SEPARATOR)));}}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;String requestURI = httpRequest.getRequestURI();if (this.isExclusion(requestURI)) {// 不过滤filterChain.doFilter(servletRequest, servletResponse);} else {// 过滤ParamsRequestWrapper requestWrapper = new ParamsRequestWrapper(httpRequest);filterChain.doFilter(requestWrapper, servletResponse);}}@Overridepublic void destroy() {}public boolean isExclusion(String requestURI) {if (this.excludesUrls == null) {return false;}for (String url : this.excludesUrls) {if (url.equals(requestURI)) {return true;}}return false;}}