在实际使用中,urlEncoding的处理

阅读更多
问题:实际使用中有个功能需要参数列表以postForm表单的形式给用户(后台通知httppost),还需要将参数列表GETFrom表单的形式给用户(前台跳转httpGET)。其中form参数中有个参数是RSA加密的结果,有特殊字符(比如说“=”号),需要urlEncoding进行转码。

转码后,客户收到请求,前台通知成功验签成功,后台通知验签失败。


问题查找:
写了个callbackAction回显代码
String body= JSON.toJSONString(getRequest().getParameterMap());
getResponse.setContentType("text/html;charset=utf-8");
Writer writer=getResponse.getWriter();
writer.write("QeryString:"+getRequest().getQueryString()+"\n");
writer.write("Body:"+body);
writer.flush();
wirter.close();


参数mac值为: abc==,urlEncode编码后abc%3d%3d。
1、前台跳转时,自己拼接路径callbackurl=url?name1=value1&name2=value2
,跳转到自己的系统的页面,在页面停留几秒,然后跳转到商户的提供的地址上。





GET请求测试:浏览器输入

http://127.0.0.1:8080/merchant-mock/callback.do?mac=abc%3d%3d

结果:页面上显示
QueryString:mac=abc%3d%3d
Body:["mac":["abc=="]]

说明:GET请求里面参数进行urlEnCode编码后会自动会被Decode回来。

但是为什么POST参数,解析后验签失败呢?带着问题找答案

2、代码中POST请求检查
代码中,将参数value进行urlEncode编码放入map中,然后通过apache的httpClient进行POST请求。
mac=URLEncoder.encode(mac,"UTF-8");
params.put("mac",mac);

httpClient hc=new DefaultHttpClient();
httpPost httpPost=new httpPost(httpUrl);
UrlEncodeFormEntity entity=new UrlEncodeFormEntity(params,encoding);
httpPost.setEntity(entity);
...
HttpResponse response=hc.execute(httpPost);

打开httpClient的源码org.apache.http.client.entity.UrlEncodeFormEntity
public UrlEncodeFormEntity(final List parameters,final String charset){

super(URLEncodedUtils.format(parameters,charset,ContentType.create(URLEncodedUtils.ContentType,charset)))
}

httpClient源码类org.apache.http.client.utils.URLEncodeUtils

public Class URLEncodeUtils{
public static final String CONTENT_TYPE="application/x-www-form-urlencoded";
public static final char QP_SEP_A='&';
public static final String NAME_VALUE_SEPARATOR="=";
public static final int RADIX =16;
...

public static String format(List parameters,String charset){
   return format(parameters,QP_SEP_A,charset)
}

public static String format(List parameters,char separator,String charset){
final StringBuilder result=new StringBuilder();
for(NameValuePair parameter:parameters){
   final String encodedName=encodeFormFields(parameter.getName(),charset);
   final String encodedValue=encodeFormFields(parameter.getValue(),charset);
   if(result.length()>0){
      result.append(separator);
   }
   result.append(encodedName);
   if(encodedValue!=null){ 
      result.append(NAME_VALUE_SEPARATOR);
      result.append(encodedValue);
   }
}
return result.toString();
}


//encodeFormFormFields进行了urlEncode编码,调用urlEncode方法
public static String urlEncode(String content,Charset charset,BitSet safechars,boolean blankAsPlus){

if(content== null){
  return null;
}
StringBuilder buf=new StringBuilder();
ByteBuffer bb=charset.encode(content);
while(bb.hasRemaining()){
   final int b = bb.get() & oxff;
   if(safechars.get(b)){  
      buf.append((char) b);
   }else if(blankAsPlus && b ==' '){
      buf.append('+');
   }else{
      buf.append("%");
      char hex1=Character.toUpperCase(Character.forDigist((b>>4)&0xf,RADIX));
      char hex2=Character.toUpperCase(Character.forDigist(b & 0xf,RADIX));
      buf.append(hex1);
      buf.append(hex2);
   }
}
return buf.toString();

}


结果:我们发现对参数做了两次urlEncoding,httpClient的UrlEncodeFormEntity自己自己拼装name1=value1&name2=vlaue2的时候已经对name和value都进行了urlEncode。使用这种方式的时候不需要主动进行urlEncoding。


你可能感兴趣的:(在实际使用中,urlEncoding的处理)