AI智能
改变未来

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


记录最近遇到的坑。

起因

账管有个信用卡绑定接口,我的调用的时候需要传号码、地址等信息,使用的是 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 的方式传送数据。请求的内容需要以…=…&…=…的格式提交,在请求体内内容将会以”&”和“ = ”进行拆分。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » httpServletRequest.getParameter 参数中存在“&”导致获取不到完整参数的问题