body区域怎么传一个数组_用户输入的虎狼之词,怎么校验之后不见了?
不知道你們有沒有對用戶輸入的東西進行過敏感校驗,如果不進行校驗,用戶屬于一些攻擊腳本,那么我們的服務就掛逼啦!所以我們首先需要通過過濾器將用戶的數據讀出來進行安全校驗,這里面涉及到一個動作,就是需要將用戶的數據在過濾器中讀出來,進行校驗,通過之后再放行。
問題
如果我們的數據是get請求倒還好,但是如果是一些數據量比較大,我們需要通過post json的方式來說傳遞數據的時候,這個時候其實是通過流的方式傳遞的,如果在過濾器中將參數讀取出來之后,然后放行,等到到Servlet的時候,@RequestBody是無法獲取到數據的,因為post json使用流傳遞,流被讀取之后就不存在了,所以我們在過濾器中讀取之后,@ReqeustBody自然就讀不到數據了,同時會報如下一個錯誤。
- 在過濾器中讀取body中的數據
@Slf4j
public class CheckUserFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
// 在過濾器中讀取數據
BufferedReader reader = request.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
System.out.println(sb.toString());
filterChain.doFilter(request, res);
}
}
- 出現異常,就是說內容已經被讀取了,你不能調用了
java.lang.IllegalStateException: UT010003: Cannot call getInputStream(), getReader() already called
at io.undertow.servlet.spec.HttpServletRequestImpl.getInputStream(HttpServletRequestImpl.java:666)
at javax.servlet.ServletRequestWrapper.getInputStream(ServletRequestWrapper.java:152)
at javax.servlet.ServletRequestWrapper.getInputStream(ServletRequestWrapper.java:152)
解決
- HttpServletRequestWrapper
那么出現這種問題怎么辦呢?能不能通過一個中間的變量將這些數據保存下來,然后我們就可以一直讀取了,這樣不就解決了這個問題了嗎?那保存在哪里呢?這個時候 HttpServletRequestWrapper 就派上用場了。
這個其實你可以把它理解為Request的包裝類,Reqeust中有的方法它都有,我們通過繼承這個類,重寫該類中的方法,將body中的參數保存一個byte數組中,然后放行的時候將這個包裝類傳遞進去,不就可以一直拿到參數了?
- 封裝Request類
private final byte[] body;
/**
* 所有參數的集合
*/
private Map parameterMap;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
BufferedReader reader = request.getReader();
body = readBytes(reader);
parameterMap = request.getParameterMap();
}
@Override
public BufferedReader getReader() throws IOException {
ServletInputStream inputStream = getInputStream();
if (null == inputStream) {
return null;
}
return new BufferedReader(new InputStreamReader(inputStream));
}
@Override
public Enumeration getParameterNames() {
Vector vector = new Vector<>(parameterMap.keySet());
return vector.elements();
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (body == null) {
return null;
}
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 listener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
/**
* 通過BufferedReader和字符編碼集轉換成byte數組
*
* @param br
* @return
* @throws IOException
*/
private byte[] readBytes(BufferedReader br) throws IOException {
String str;
StringBuilder retStr = new StringBuilder();
while ((str = br.readLine()) != null) {
retStr.append(str);
}
if (StringUtils.isNotBlank(retStr.toString())) {
return retStr.toString().getBytes(StandardCharsets.UTF_8);
}
return null;
}
}
- 將過濾器改造
@Slf4j
public class CheckUserFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
// 從Request的包裝類中讀取數據
BufferedReader reader = requestWrapper.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
System.out.println(sb.toString());
filterChain.doFilter(requestWrapper, res);
}
}
經過這樣的配置之后,我們即使在過濾器中獲取了參數,請求也會到達Servlet。
如果基礎知識IO那塊不是很扎實的話,第一眼看到這個問題確實挺懵逼的。我也是百度之后解決的,確實值得記錄一下,有時候我們會對所有請求進來的參數進行保存輸出什么的,這個時候如果是post json數據的話,如果不是特別明白,可能也會出現這種問題。
日拱一卒,功不唐捐
今日推薦RabbitMQ工作隊列之公平分發(fā)消息與消息應答(ACK)
如何利用RabbitMQ生產一個簡單的消息
RabbitMQ如何高效的消費消息
好文章,我在看
總結
以上是生活随笔為你收集整理的body区域怎么传一个数组_用户输入的虎狼之词,怎么校验之后不见了?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eclipse文本框输出mysql全部数
- 下一篇: 庄闲分析软件安卓版_关于公布湖南省202