请求数据含有特殊字符进行转义的过滤器-Java

一、继承HttpServletRequestWrapper创建自定义请求包装器

需要重写的方法

1、getParameterMap

2、getParameter

3、getParameterValues

4、getInputStream

5、getReader

代码如下

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Map;

/**
 * 特殊字符转义请求包装器
 * 请求中含有特殊字符的数据进行转义
 */
public class SpecialCharRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 特殊字符映射集合
     * 示例:{"<", "&lt;"}
     */
    private final Map<String, String> map;

    /**
     * 构造器
     *
     * @param request 请求
     * @param map 特殊字符映射集合
     */
    public SpecialCharRequestWrapper(HttpServletRequest request, Map<String, String> map) {
        super(request);
        this.map = map;
    }

    /**
     * 获取参数map集合
     */
    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> parameterMap = super.getParameterMap();
        if (parameterMap != null) {
            parameterMap.forEach((key, value) -> parameterMap.put(key, this.getParameterValues(key)));
        }
        return parameterMap;
    }

    /**
     * 根据参数名获取值
     */
    @Override
    public String getParameter(String name) {
        return escape(super.getParameter(name));
    }

    /**
     * 根据参数名获取所有的值
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] parameterValues = super.getParameterValues(name);
        if (parameterValues != null) {
            for (int i = 0; i < parameterValues.length; i++) {
                parameterValues[i] = escape(parameterValues[i]);
            }
        }
        return parameterValues;
    }

    /**
     * 获取body数据
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        // 读取body
        ServletInputStream sis = super.getInputStream();
        // 加载body
        ObjectMapper om = new ObjectMapper();
        JsonNode jsonNode = om.readTree(sis);
        // 创建待处理列表并添加节点
        LinkedList<JsonNode> linkedList = new LinkedList<>();
        linkedList.add(jsonNode);
        // 循环对body进行转义
        while (!linkedList.isEmpty()) {
            JsonNode node = linkedList.removeFirst();
            // 检查是否为对象节点
            if (node.isObject()) {
                ObjectNode on = (ObjectNode) node;
                // 遍历对象节点
                node.fields().forEachRemaining(entry -> {
                    // 获取节点各字段的值
                    JsonNode entryValue = entry.getValue();
                    if (!entryValue.isNull()) {
                        // 检查值是否为文本
                        if (entryValue.isTextual()) {
                            // 对值进行转义,并对节点重新赋值
                            on.put(entry.getKey(), escape(entryValue.asText()));
                        }
                        // 检查值是否为对象节点或数组节点
                        if (entryValue.isObject() || entryValue.isArray()) {
                            // 节点加入待处理列表中
                            linkedList.add(entryValue);
                        }
                    }
                });
            }
            // 检查是否为数组节点
            if (node.isArray()) {
                ArrayNode an = (ArrayNode) node;
                // 遍历数组节点
                for (int i = 0; i < node.size(); i++) {
                    // 获取数组节点索引位置的值
                    JsonNode arrayValue = node.get(i);
                    if (!arrayValue.isNull()) {
                        // 检查值是否为文本
                        if (arrayValue.isTextual()) {
                            // 对值进行转义,并对节点重新赋值
                            an.set(i, new TextNode(escape(arrayValue.asText())));
                        }
                        // 检查值是否为对象节点或数组节点
                        if (arrayValue.isObject() || arrayValue.isArray()) {
                            // 节点加入待处理列表中
                            linkedList.add(arrayValue);
                        }
                    }
                }
            }
        }
        // 把转义完的json数据转成字节数组输入流
        final ByteArrayInputStream bais = new ByteArrayInputStream(om.writeValueAsBytes(jsonNode));
        // 创建新的流
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                // todo 自定义操作
                return false;
            }

            @Override
            public boolean isReady() {
                // todo 自定义操作
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {
                // todo 自定义操作
            }

            @Override
            public int read() throws IOException {
                // 通过bais读取转义完的数据
                return bais.read();
            }
        };
    }

    /**
     * 获取body读取器
     */
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    /**
     * 转义方法
     */
    private String escape(String value) {
        // 空值直接返回
        if (value == null) {
            return null;
        }
        // 遍历字符串检查各个字符是否为特殊字符并进行转义
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < value.length(); i++) {
            String charValue = String.valueOf(value.charAt(i));
            sb.append(map.getOrDefault(charValue, charValue));
        }
        return sb.toString();
    }

}

二、继承OncePerRequestFilter或者实现Filter创建自定义过滤器

两种方式选择其中一个

继承OncePerRequestFilter(Spring中)

1、创建过滤器

import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 特殊字符过滤器
 */
@Configuration
public class SpecialCharFilter extends OncePerRequestFilter {

    /**
     * 特殊字符集合
     */
    private Map<String, String> map = new HashMap<String, String>() {{
        put("\"", "&quot;");
        put("<", "&lt;");
        put(">", "&gt;");
        put("?", "&iexcl;");
        put("¥", "&yen;");
        put("|", "&brvbar;");
        put("′", "&acute;");
    }};

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 传入自定义的请求包装器
        filterChain.doFilter(new SpecialCharRequestWrapper(request, map), response);
    }

}

实现Filter(Spring中)

1、创建过滤器

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 特殊字符过滤器
 */
public class SpecialCharFilter implements Filter {

    /**
     * 特殊字符集合
     */
    private Map<String, String> map = new HashMap<String, String>() {{
        put("\"", "&quot;");
        put("<", "&lt;");
        put(">", "&gt;");
        put("?", "&iexcl;");
        put("¥", "&yen;");
        put("|", "&brvbar;");
        put("′", "&acute;");
    }};

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 传入自定义的请求包装器
        chain.doFilter(new SpecialCharRequestWrapper((HttpServletRequest) request, map), response);
    }

}

2、注册过滤器 

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<SpecialCharFilter> getSpecialCharFilter() {
        FilterRegistrationBean<SpecialCharFilter> registrationBean = new FilterRegistrationBean<>();
        // 添加过滤器
        registrationBean.setFilter(new SpecialCharFilter());
        // 全部路径都过滤
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }

}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值