您的位置:首页 > 产品设计 > UI/UE

httpServletRequest.getParameter 参数中存在“&”导致获取不到完整参数的问题

2020-08-27 14:29 411 查看

记录最近遇到的坑。

起因

账管有个信用卡绑定接口,我的调用的时候需要传号码、地址等信息,使用的是 HttpURLConnection,发送的时候将参数转为key=value&key=value 的形式,账管那边使用 httpServletRequest.getParameter() 进行获取参数。
问题就是当某些地址中存在 & 符号的时候,因为账管获取参数的时候是通过 & 符号进行截取的,就会导致他们获取参数不全。
如:a=123&b=park&center
本来 b 的 value 应该是 park&center,现在他们那边只能获取到 park,这就导致两边参数不一样,签名也不一样,然后验签失败。

解决方案

以上就是事情的起因,期初我的建议是他们那边能不能换成 json 格式的接收,我们这边直接发送 json 格式的数据,这样应该不会有问题,但是他们死活不愿意改。
后续方案是我们将参数中的 & 进行 URL 编码,将其转化为 %26。

我们实现的方法大概如下:

public String pay(String url, Map<String, String> params) {
URL u = null;
HttpURLConnection con = null;
// 构建请求参数
StringBuffer sb = new StringBuffer();
String strResult = null;
if (params != null) {
for (Entry<String, String> e : params.entrySet()) {
sb.append(e.getKey());
sb.append("=");
sb.append(e.getValue());
sb.append("&");
}
strResult = sb.substring(0, sb.length() - 1);
}

// 尝试发送请求
try {
u = new URL(url);
con = (HttpURLConnection) u.openConnection();
// POST 只能为大写,严格限制,post会不识别
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
osw.write(sb.toString());
osw.flush();
osw.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (con != null) {
con.disconnect();
}
}
// 读取返回内容
StringBuffer buffer = new StringBuffer();
try {
//一定要有返回值,否则无法把请求发送给server端。
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
String temp;
while ((temp = br.readLine()) != null) {
buffer.append(temp);
}
} catch (Exception e) {
logger.error("*****报错:", e);
}

return buffer.toString();
}

改造为:

String value = e.getValue();
if (value.contains("&")) {
try {
// URL编码,针对“&”进行处理,防止截取参数不完整导致验签失败
value = URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
}
sb.append(value);

分析原因

使用 httpServletRequest.getParameter 接收post请求参数,发送端 content Type 必须设置为 application/x-www-form-urlencoded;否则会接收不到

使用 httpServletRequest.getParameter 也是获取不到 json 格式的数据的,发送端只能发送 key=value&key=value 格式的数据。所以如果需要发送 json 格式的数据,两边都需要进行改造。

application/x-www-form-urlencoded 通过表单提交,在sevlet实现中,mutipart/form-data 和 application/x-www-form-urlencoded 会被特殊处理,请求参数将被放置于 request.paramter,这是一个map。
我们可以从map中获取参数进行验证,或者其他拦截需求,map的获取类似hibernate的延迟加载,当调用 request.getparamter() 方法,servlet才会从请求流中读取请求参数加载入map。InputStream 也会存有这份数据,但如果这份数据被读取,那么到了controller层将无法读出数据,同样,拦截之后到达controller层时请求数据已经被加载入了controller层方法实参,实参对象需要有set方法,框架会以反射的方式调用属性的set方法注入数据,数据只会被注入到已有的属性。

当以 application/json 的 content-type 传送数据,被传送的对象只需被json序列化。当以 application/x-www-form-urlencoded 的方式传送数据。请求的内容需要以…=…&…=…的格式提交,在请求体内内容将会以”&”和“ = ”进行拆分。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐