body区域怎么传一个数组_用户输入的虎狼之词,怎么校验之后不见了?
不知道你們有沒有對(duì)用戶輸入的東西進(jìn)行過敏感校驗(yàn),如果不進(jìn)行校驗(yàn),用戶屬于一些攻擊腳本,那么我們的服務(wù)就掛逼啦!所以我們首先需要通過過濾器將用戶的數(shù)據(jù)讀出來進(jìn)行安全校驗(yàn),這里面涉及到一個(gè)動(dòng)作,就是需要將用戶的數(shù)據(jù)在過濾器中讀出來,進(jìn)行校驗(yàn),通過之后再放行。
問題
如果我們的數(shù)據(jù)是get請(qǐng)求倒還好,但是如果是一些數(shù)據(jù)量比較大,我們需要通過post json的方式來說傳遞數(shù)據(jù)的時(shí)候,這個(gè)時(shí)候其實(shí)是通過流的方式傳遞的,如果在過濾器中將參數(shù)讀取出來之后,然后放行,等到到Servlet的時(shí)候,@RequestBody是無法獲取到數(shù)據(jù)的,因?yàn)閜ost json使用流傳遞,流被讀取之后就不存在了,所以我們?cè)谶^濾器中讀取之后,@ReqeustBody自然就讀不到數(shù)據(jù)了,同時(shí)會(huì)報(bào)如下一個(gè)錯(cuò)誤。
- 在過濾器中讀取body中的數(shù)據(jù)
@Slf4j
public class CheckUserFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
// 在過濾器中讀取數(shù)據(jù)
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);
}
}
- 出現(xiàn)異常,就是說內(nèi)容已經(jīng)被讀取了,你不能調(diào)用了
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
那么出現(xiàn)這種問題怎么辦呢?能不能通過一個(gè)中間的變量將這些數(shù)據(jù)保存下來,然后我們就可以一直讀取了,這樣不就解決了這個(gè)問題了嗎?那保存在哪里呢?這個(gè)時(shí)候 HttpServletRequestWrapper 就派上用場(chǎng)了。
這個(gè)其實(shí)你可以把它理解為Request的包裝類,Reqeust中有的方法它都有,我們通過繼承這個(gè)類,重寫該類中的方法,將body中的參數(shù)保存一個(gè)byte數(shù)組中,然后放行的時(shí)候?qū)⑦@個(gè)包裝類傳遞進(jìn)去,不就可以一直拿到參數(shù)了?
- 封裝Request類
private final byte[] body;
/**
* 所有參數(shù)的集合
*/
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和字符編碼集轉(zhuǎn)換成byte數(shù)組
*
* @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的包裝類中讀取數(shù)據(jù)
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);
}
}
經(jīng)過這樣的配置之后,我們即使在過濾器中獲取了參數(shù),請(qǐng)求也會(huì)到達(dá)Servlet。
如果基礎(chǔ)知識(shí)IO那塊不是很扎實(shí)的話,第一眼看到這個(gè)問題確實(shí)挺懵逼的。我也是百度之后解決的,確實(shí)值得記錄一下,有時(shí)候我們會(huì)對(duì)所有請(qǐng)求進(jìn)來的參數(shù)進(jìn)行保存輸出什么的,這個(gè)時(shí)候如果是post json數(shù)據(jù)的話,如果不是特別明白,可能也會(huì)出現(xiàn)這種問題。
日拱一卒,功不唐捐
今日推薦RabbitMQ工作隊(duì)列之公平分發(fā)消息與消息應(yīng)答(ACK)
如何利用RabbitMQ生產(chǎn)一個(gè)簡單的消息
RabbitMQ如何高效的消費(fèi)消息
好文章,我在看
總結(jié)
以上是生活随笔為你收集整理的body区域怎么传一个数组_用户输入的虎狼之词,怎么校验之后不见了?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eclipse文本框输出mysql全部数
- 下一篇: 庄闲分析软件安卓版_关于公布湖南省202