参考
Spring Boot之RestTemplate在URL中转义字符禁止转义的问题解决
问题复现
最近在做一个拖曳验证码的功能,需要在url后面将verify的字符串附上再由服务端进行比对。问题就出在这里了。
使用的是springBoot的resetTemplate,发现了一个问题,
客户端得到的校验字符为:
/xB55xDWN4ggI1BI9vaSnO82505DZWky0nKm5Y0z/49LwshUcgQCSY/v5a+XT865iO57+LbTFg0+7sZwBcT9Tw==
通过resetTemplate编码后的url为:
/api/user/loginByAccnt?captchaVerification=/xB55xDWN4ggI1BI9vaSnO82505DZWky0nKm5Y0z/49LwshUcgQCSY/v5a+XT865iO57+LbTFg0+7sZwBcT9Tw%3D%3D
服务端获得的校验字符为:
/xB55xDWN4ggI1BI9vaSnO82505DZWky0nKm5Y0z/49LwshUcgQCSY/v5a XT865iO57 LbTFg0 7sZwBcT9Tw==
中间是有空格的。。。
一比较,首先一个就是+ 号 没有转换。。。服务端识别成为空格了。
拿encodeURIComponent来试试,可以得到:
/api/user/loginByAccnt?captchaVerification=%2FxB55xDWN4ggI1BI9vaSnO82505DZWky0nKm5Y0z%2F49LwshUcgQCSY%2Fv5a%2BXT865iO57%2BLbTFg0%2B7sZwBcT9Tw%3D%3D
嗯?具体查找一下资料,发现问题:
根据 RFC 3986 加号等符号的确实可以出现在参数中的,而且不需要编码,有问题的在于服务端的解析没有与时俱进
注意SpringBoot2.0版本的url参数编码,默认只会针对 = 和 & 进行处理;为了兼容我们一般的后端的url编解码处理在需要编码参数时
好了,发现是springBoot的ResetTemplate逻辑太新了。
下面得到解决方案:
方案1:
//伪代码
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(desktopConfig.apiUrl+"/"+this._login_uri_by_userName).queryParam("captchaVerification", URLEncoder.encode(captchaVerification,StandardCharsets.UTF_8.toString()));URI realURI=builder.build(true).toUri();
方案2:
//伪代码
String dataurl=WebTools.Json2URL(desktopConfig.apiUrl+
"/"+this._login_uri_by_userName,queryParas);
URI realURI=new URI(dataurl);
//Json2URL定义:public static String Json2URL(String url,Map<String,String> json){if(json==null||json.size()<1){return url;}String _url=url;if(ValidateUtils.isEmpty(url)){_url="";}_url=normalizeUrl(_url.trim());List<String> _paras=new ArrayList<>();int para_num=0;for(String _key:json.keySet()){if(ValidateUtils.isEmpty(_key)){continue;}para_num++;String valStr="";try{valStr=URLEncoder.encode(json.get(_key),StandardCharsets.UTF_8.toString());}catch (Exception ed){ed.printStackTrace();}_paras.add(String.format("%s=%s",_key.trim(),valStr));}if(para_num>0){if(_url.indexOf("?")!=-1){return _url+"&"+StringUtils.join(_paras,"&");}else{return _url+"?"+StringUtils.join(_paras,"&");}}else{return _url;}}