日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

body区域怎么传一个数组_用户输入的虎狼之词,怎么校验之后不见了?

發(fā)布時(shí)間:2024/10/5 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 body区域怎么传一个数组_用户输入的虎狼之词,怎么校验之后不见了? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

不知道你們有沒有對(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ù)
@WebFilter
@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)用了
{ "id":"1", "username":"bingfeng"}
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類
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

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;
}
}
  • 將過濾器改造
@WebFilter
@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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。