在 Filter 中对 request 中的 body 进行参数签名校验, 会报如下错误:

getReader() has already been called for this request

原因是 request.getReader() 和 request.getInputStream() 都是只能调用一次

并且 getReader() 方法底层也是调用 getInputStream() 来实现的.

所以我们要使用 HttpServletRequestWrapper 来实现自定义的 CustomHttpServletRequestWrapper, 把 body 保存在 CustomHttpServletRequestWrapper 中, 并且重写 getInputStream() 方法

重写  HttpServletRequestWrapper

package com.fosung.pb.village.config;import org.apache.commons.fileupload.servlet.ServletFileUpload;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.nio.charset.StandardCharsets;public class MyRequestWrapper extends HttpServletRequestWrapper {private byte[] body;public MyRequestWrapper(HttpServletRequest request) throws IOException {super(request);if(ServletFileUpload.isMultipartContent(request)){return;}StringBuilder sb = new StringBuilder();String line;BufferedReader reader = request.getReader();while ((line = reader.readLine()) != null) {sb.append(line);}String body = sb.toString();this.body = body.getBytes(StandardCharsets.UTF_8);}public String getBody() {return new String(this.body , StandardCharsets.UTF_8) ;}@Overridepublic ServletInputStream getInputStream() {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read(){return bais.read();}};}@Overridepublic BufferedReader getReader(){return new BufferedReader(new InputStreamReader(this.getInputStream()));}
}

Filter 使用

package com.fosung.pb.village.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author lanx* @date 2022/4/11*/
@Slf4j
@Component
@WebFilter(filterName = "AntiSqlInjectionfilter", urlPatterns = "/*")
public class AntiSqlInjectionfilter implements Filter {public void destroy() {// TODO Auto-generated method stub}public void init(FilterConfig arg0) throws ServletException {// TODO Auto-generated method stub}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse res = (HttpServletResponse) response;MyRequestWrapper myRequestWrapper = null;// 获取请求bodytry {myRequestWrapper = new MyRequestWrapper(req);} catch (IOException e) {log.error("get request body exception", e);throw new RuntimeException(e);}if ("POST".equalsIgnoreCase(req.getMethod())) {String param = myRequestWrapper.getBody();chain.doFilter(myRequestWrapper, response);} else {chain.doFilter(myRequestWrapper, response);}}}

解决:getReader() has already been called for this request相关推荐

  1. getInputStream/getReader() has already been called for this request

    getInputStream/getReader() has already been called for this request 一.背景 定义了一个安全校验过滤器,现在要获取请求参数. 通过r ...

  2. java getreader_异常处理:getReader() has already been called for this request

    场景描述: 在 Spring Boot 自定义拦截器中,需要对请求 body 中的内容做签名验证.在日志切面中,需要打印请求 body 中的内容. 报错内容: java.lang.IllegalSta ...

  3. 客户端向服务端传送特殊字符解决方法(检测到有潜在危险的 Request.Form 值)

    当客户端向服务端传输特殊字符时报错,错误信息如下图: 在asp.net中Request提交时出现有html代码或javascript等字符串时,程序系统会认为其具有潜在危险的值.环境配置会报出&quo ...

  4. getReader() has already been called for this request

    问题现场: 原因: HttpServletRequest 的 getInputStream() 和 getReader() 都只能读取一次. 因为 我们使用@RequestBody 注解,读取body ...

  5. 异常:getReader() has already been called for this request

    一个流不能读两次异常,这种异常一般出现在框架或者拦截器中读取了request中的流的数据,我们在业务代码中再次读取(如@requestBody),由于流中的数据已经没了,所以第二次读取的时候就会抛出异 ...

  6. XShell免费版的安装配置教程以及使用教程—解决“WARNINGThe remote SSH server rejected X11 forwarding request.“警告

    目录 一.简介 二.XShell的作用 三.下载XShell 四.使用XShell连接Linux服务器 1.XShell初始化界面 2.点击"新建",新建会话 3. 填写会话信息 ...

  7. 解决 [HPM] Error occurred while trying to proxy request

    之前vue运行访问接口本来没有问题的,今天突然访问老是出现这个问题,常见情况有以下情况,比如: 1.网络不稳定的原因(我就是这种),气气!!!. 2.代理的接口写错, 3.端口被占用 4.后台服务地址 ...

  8. 解决consul出现I/O error on GET request for “http://XXX“: XXX错误

    原因: 在编写RestTemplate配置类时忘记添加@LoadBalanced注解.添加后解决,代码如下: @Configuration public class ApplicationContex ...

  9. TS:解决docker无法启动,报:start request repeated too quickly for docker.service错误-2021.12.08(已解决)

    目录 文章目录 目录 1.报错现象 2.解决办法 3.总结 关于我 最后 1.报错现象 首先,我当前的环境是:docker 20.10.11,vmworkstation虚机 很奇怪,自己的docker ...

最新文章

  1. java $ 用法_Java的Volatile实例用法及讲解
  2. ibm ilog mysql_开源纯C日志函数库iLOG3快速入门(八、如果你喜欢简单日志函数甚于日志函数库)...
  3. 打开qq农场外挂显示无法与服务器同步,稍后再试是怎么回事啊,qq农场为什么打不开...
  4. 兆比特每秒和兆字节每秒_Mbps和MB/S一样吗?我们平时经常说的多少M带宽是哪个?...
  5. 面试系列-2 我终于弄清楚了redis数据结构之string应用场景
  6. oracle rac告警,oracle11.2.0.4 RAC 日志总有告警
  7. 非零基础自学Golang 第18章 HTTP编程(下) 18.2 HTTP服务端 18.2.2 启动HTTP服务器 18.2.3 启动HTTPS服务器
  8. 有趣的编程(一)——海盗分金币问题如何编程求解
  9. 计算机图形学 学习笔记 图元的属性
  10. 谷歌地图街景图中可查看照片拍摄日期
  11. 一座小桥(最多只能承重两个人)横跨南北两岸,任意时刻同一方向只允许一个人过桥,南侧桥段和北侧桥段较窄只能通过一个人,桥中央一处宽敞,允许两个人通过或歇息。试用P(wait)V(signal)操作实现
  12. 通过超级终端连接短信猫, 用at指令发短信和打电话
  13. #1135 : Magic Box(枚举)
  14. 酷狗登陆服务器正在升级维护,酷狗直播认证歌手等级热度维护
  15. 【设计模式】外观模式代理模式中介者模式的区别
  16. word转换成excel格式的完美方法
  17. 避免2.4GHz ISM频段各种类型无线设备干扰的技术 1
  18. 广州市黄埔区科技局关于开展区配套科技项目逾期未验收项目清理工作的通知
  19. 联邦学习开源框架调研
  20. 全球最年长的跳伞者!澳大利亚百岁寿星已经是第三次跳伞了!

热门文章

  1. ORA-00257: archiver error. Connect internal only, until freed 错误解决方案
  2. 《冰封王座》世界魔兽界十大叱咤风云人物
  3. java序列化算法透析_Java序列化算法透析
  4. 手机QQ协议抓包教程
  5. SqlServer 修改数据库文件位置
  6. 添加 frida-gadget 到安卓应用(无须 root)
  7. Python 爬虫 数据提取
  8. 信息安全:BYOD切忌安全过头
  9. 计算机里面哪个代表度,二叉树中的度是什么?
  10. 经典好文!手把手教你写Android项目文档,小白也能看明白