在开发中常常遇到一种场景,一个系统向另一个系统提交数据的时候,可能是通过json方式提交,也可能先写到html页面的form表单里面提交,这样就会带来几个问题,比如,json格式里面含有疑似XSS攻击的恶意字符串,或者含有与HTML语义相同的标签字符。
在这种情况下,就需要对所提交的字符串进行编码了。然后接收方进行解码。
编码的常见方式总结如下:
一、unicode编码
//import org.apache.commons.lang.StringEscapeUtils;
String test="我是中国人()(),,<br>\",.<script><tablke>";
String encoderJava=StringEscapeUtils.escapeJava(test);
String unencoderJava=StringEscapeUtils.unescapeJava(encoderJava);
System.out.println(encoderJava);
System.out.println(unencoderJava);
System.out.println("---------------------------------------------------------");
结果:
\u6211\u662F\u4E2D\u56FD\u4EBA()\uFF08\uFF09\uFF0C,<br>\",.<script><tablke>
我是中国人()(),,<br>",.<script><tablke>
二、Base64与Base32
//import org.apache.commons.codec.binary.Base64;
byte[] base64=Base64.encodeBase64(test.getBytes());
String base64Str=new String(base64);
byte[] decodeBase64= Base64.decodeBase64(base64Str);
String decodeBase64Str=new String(decodeBase64);
System.out.println(base64Str);
System.out.println(decodeBase64Str);
结果:
5oiR5piv5Lit5Zu95Lq6KCnvvIjvvInvvIwsPGJyPiIsLjxzY3JpcHQ+PHRhYmxrZT4=
我是中国人()(),,<br>",.<script><tablke>
Base32类似
三、只针对html字符转义的编码
这里有两个包提供了html的转义编码功能,但是差别很大
分别是org.apache.commons.lang.StringEscapeUtils; 与org.springframework.web.util.HtmlUtils;
先看StringEscapeUtils,如下:
String encoderHtml=StringEscapeUtils.escapeHtml(test);
String unencoderHtml=StringEscapeUtils.unescapeHtml(encoderHtml);
System.out.println(encoderHtml);
System.out.println(unencoderHtml);
System.out.println("---------------------------------------------------------");
结果:
我是中国人()(),,<br>",.<script><tablke>
我是中国人()(),,<br>",.<script><tablke>
再看HtmlUtils的效果:
String springEncodeHtml=HtmlUtils.htmlEscape(test);
String unspringEncodeHtml=HtmlUtils.htmlUnescape(springEncodeHtml);
System.out.println(springEncodeHtml);
System.out.println(unspringEncodeHtml);
结果:
我是中国人()(),,<br>",.<script><tablke>
我是中国人()(),,<br>",.<script><tablke>
四、url编码
这里使用commons-codec包提供的功能
byte[] url=URLCodec.encodeUrl(new BitSet(),test.getBytes());
byte[] decodeUrl=URLCodec.decodeUrl(url);
String urlStr=new String(url);
String decodeUrlStr=new String(decodeUrl);
System.out.println(urlStr);
System.out.println(decodeUrlStr);
结果:
5oiR5piv5Lit5Zu95Lq6KCnvvIjvvInvvIwsPGJyPiIsLjxzY3JpcHQ+PHRhYmxrZT4=
我是中国人()(),,<br>",.<script><tablke>
五、其他编码方式(http://commons.apache.org/proper/commons-codec)
commons-codec 还提供了很多其他的编码方式,这里列出一种。
byte[] qByte=QuotedPrintableCodec.encodeQuotedPrintable(new BitSet(),test.getBytes());
byte[] dByte=QuotedPrintableCodec.decodeQuotedPrintable(qByte);
String qByteStr=new String(qByte);
String dByteStr=new String(dByte);
System.out.println(qByteStr);
System.out.println(dByteStr);
结果:
%E6%88%91%E6%98%AF%E4%B8%AD%E5%9B%BD%E4%BA%BA%28%29%EF%BC%88%EF%BC%89%EF%BC%8C%2C%3C%62%72%3E%22%2C%2E%3C%73%63%72%69%70%74%3E%3C%74%61%62%6C%6B%65%3E
我是中国人()(),,<br>",.<script><tablke>
通过以上五种编码方式,发现不满足我需求的除了第一种和第三种里面的HtmlUtils之外,其余都满足我的需求。编码后字符长度最小的是第二种和第三种里面的StringEscapeUtils
另:我希望找到一种这样的编码方式,提交请求对方接受后,不需要转码就能使用。有吗?
org.springframework.web.util.HtmlUtils; 提供的编码方式仅仅将HTML字符进行了转义,HTML转义字符push到页面后,提交到后台,后台通过request.getParameter获取,并不需要对获取到的数据进行解码。浏览器能自动解码。这个例子与浏览器URL字符串自动对中文进行编码解码原理类似
举例如下:
jdjg<input id =""> 转码后为 jdjg<input id ="">此时HTML源码如下:
value="jdjg<input id ="">" >
页面展示效果为:
实际后台获取到的值为:
jdjg<input id ="">