[英]How to parse Http POST response body in Java
为标准 JDK lib 接收 html 表单帖子,并使用 HttpExchange 获取并传递给
private String getBodyString(HttpExchange he){
String ret=null;
InputStream is = he.getRequestBody();
URLDecoder dc = new URLDecoder();
try {
ret = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)).readLine();
ret = dc.decode(ret, StandardCharsets.UTF_8.name());
}catch (NullPointerException ex){
Logger.getLogger(RequestBodyParser.class.getName()).log(Level.SEVERE, null, ex);
}catch (IOException ex) {
Logger.getLogger(RequestBodyParser.class.getName()).log(Level.SEVERE, null, ex);
}
return ret;
}
返回:
mytxt1=huhu&mytxt2=haha&btnOk=1
其中 mytxt1 和 mytxt2 是输入。 现在我想从中解析键(名称)和值(文本)。
这是一个很好的例子。 我可以很容易地用“&”进行一些字符串拆分,并用“=”划分键和值。 但也有不好的地方:
mytxt1=huhu & haha &mytxt2=haha&btnOk=1
...和丑陋的:
mytxt1=Lorem &mytxt2=Ugly Injection&mytxt2=haha&btnOk=1
而且我还没有开始谈论“选择多个”。 是否有任何最佳实践可以使用包含的 JDK 库以安全的方式解析表单条目?
首先, URLDecoder.decode 是一个 static 方法。 调用时不要创建 URLDecoder 的实例。 (事实上, 该构造函数现在已被弃用。 )
其次,不要捕获 NullPointerException。 NullPointerException 表示程序员犯了一个错误。 如果发生 NullPointerException,程序员需要修复错误,而不是隐藏它。
第三,您不应将整个查询传递给单个 URLDecoder.decode 调用。 当您这样做时,您将失去区分实际表示查询参数名称和值的&
和=
字符以及实际名称或值中存在的&
和=
字符的能力。
例如,如果我从这个查询开始:
candy=M%26Ms&fruit=pineapple
然后我将整个查询传递给 URLDecoder.decode,我最终得到这个:
candy=M&Ms&fruit=pineapple
现在程序无法知道只有两个参数, candy
和fruit
。 现在看来有三个: candy
、 Ms
(没有对应的值)和fruit
。
解决这个问题的方法是首先拆分参数,然后拆分键/值对,然后解码每个键和值。
private Map<String, List<String>> getBodyString(HttpExchange he) {
Map<String, List<String>> parameters = new LinkedHashMap<>();
String query;
try (InputStream body = he.getRequestBody()) {
query = new String(body.readAllBytes(), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
String[] keyValuePairs = query.split("&");
for (String keyValuePair : keyValuePairs) {
String[] keyAndValue = keyValuePair.split("=", 2);
String key = keyAndValue[0];
String value = keyAndValue.length > 1 ? keyAndValue[1] : "";
key = URLDecoder.decode(key, StandardCharsets.UTF_8);
value = URLDecoder.decode(value, StandardCharsets.UTF_8);
parameters.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
}
return parameters;
}
目前 Java SE 中没有用于解析查询参数的方法(尽管许多人都要求它)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.