欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在实际使用中,urlEncoding的处理  

程序员文章站 2024-03-23 18:46:58
...
问题:实际使用中有个功能需要参数列表以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
,跳转到自己的系统的页面,在页面停留几秒,然后跳转到商户的提供的地址上。

<script type="text/javascript">
var url=${callbackurl};
function callBack(){
   if(url && url!=null && ""!=url){  
      window.location.href=url;
   } else {
      closeWebPage();
   }
}
</script>



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<? extends NameValuePair> 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。