在 Filter 中對(duì) request 中的 body 進(jìn)行參數(shù)簽名校驗(yàn), 會(huì)報(bào)如下錯(cuò)誤:
getReader() has already been called for this request
原因是 request.getReader() 和 request.getInputStream() 都是只能調(diào)用一次
并且 getReader() 方法底層也是調(diào)用 getInputStream() 來(lái)實(shí)現(xiàn)的.
所以我們要使用 HttpServletRequestWrapper 來(lái)實(shí)現(xiàn)自定義的 CustomHttpServletRequestWrapper, 把 body 保存在 CustomHttpServletRequestWrapper 中, 并且重寫(xiě) getInputStream() 方法
重寫(xiě)? 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) ;
? ? }
? ? @Override
? ? public ServletInputStream getInputStream() {
? ? ? ? final ByteArrayInputStream bais = new ByteArrayInputStream(body);
? ? ? ? return new ServletInputStream() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isFinished() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isReady() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void setReadListener(ReadListener readListener) {
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public int read(){
? ? ? ? ? ? ? ? return bais.read();
? ? ? ? ? ? }
? ? ? ? };
? ? }
? ? @Override
? ? public BufferedReader getReader(){
? ? ? ? return new BufferedReader(new InputStreamReader(this.getInputStream()));
? ? }
}
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;
? ? ? ? // 獲取請(qǐng)求body
? ? ? ? try {
? ? ? ? ? ? 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);
? ? ? ? }
? ? }
}
原因是 request.getReader() 和 request.getInputStream() 都是只能調(diào)用一次。
原文鏈接:https://blog.csdn.net/woaiwojialanxi/article/details/124111799