在《【JavaScript】某些字符不转义可以导致网页崩溃与涉及转义字符的显示方法》(点击打开链接)提及到一种表单之前,必须把表单的输入框的内容转义的方法,但是,其实这种字符串的转义更加应该放在后台中进行。这样同时能够有效地防止sql注入的问题。
所谓的sql注入是什么呢?比如,你做了一个登录功能什么的。你必须把根据用户输入的用户名,查询存放在数据库的密码的,然后与密码比对是不是?
select语句一般这样写select username,password from userinfo表 where username=传过来的参数。
好了,如果这时候用户在自己的登录名输入a;drop database;,或者a or 1=1;则能把你的数据删除,或者任何情况都可能登录之类的,再或者能够导致你的tomcat被异常信息弄到崩溃。
同时,如果你不转义,就入库,就算用户是一个善意输入,也能够导致你的网页崩毁。
比如用户只是在交流输入框的写法,输入的内容有 <input type="text" /> 之类的,你再于数据库查询出来,则会导致你该显示<input type="text" />这个部分,变成了一个输入框。这还是小事。如果某些别有用心的用户,构造一个<form action="xx" />的表单,足以造成跨站攻击。
因此,我们对于一些不应该存在的数据,必须进行转义显示。
这里,《【JavaScript】某些字符不转义可以导致网页崩溃与涉及转义字符的显示方法》(点击打开链接)、与下面介绍的方法,用一种就可以了,否则多种字符转义的方法冲突,<转成& lt;又被你转成& amp; lt;那么用户看到的则是& lt; ,非常让人迷惑。同时注意《【jQuery】网页文本格式编辑器xheditor》(点击打开链接)这个编辑器,在提交表单就会自动帮你完成转义的。总之最后的意思就是,对于那些带编辑器的文本框,你Encode了多少次,就应该Decode多少次。对于那些单行文本框,我们只需要Encode,不对其进行Decode,因为我们推定其没有格式的!
注意:如下代码的&都用全角表示了,应该使用半角的,但是半角的&会被csdn吞了,可见csdn都已经对这些符号处理好才敢上来看网站的!
同时,还需要注意的是,某些符号在replaceAll方法的写法,毕竟replaceAll第一个参数是填正则表达式的,某些符号会对正则表达式产生冲突的。
public class EncodeDecodeUtil { /* * 所有文本框,都必须先经过htmlEncode再入库(防sql注入) * 所有显示,如果是单行文本框无须经过htmlDecode * 定义:单行文本框输入的内容都是没有格式的内容 推定:所有在单行文本框输入html标签的都是不良行为 * 带编辑器的多行文本框的内容应该经过htmlDecode,保持其固有格式 * 注意到script已经被强力转义不再decode还原,因此给你有格式又怎么样? */ public static String htmlEncode(String html) { if (html != null) { // 必要 return html .replaceAll("&", "&amp;") .replaceAll("<", "&lt;") .replaceAll(">", "&gt;") .replaceAll("\"", "&quot;") .replaceAll(" ", "&nbsp;") // 一些可能出现问题的半角符号,还是要转义的。 // ,+、*、|、\、?等符号在正则表达示中有相应的不同意义。要写成\\,\\+之类 .replaceAll("[+]", "+") .replaceAll("-", "-") // \最为特殊,对于正则表达式敏感也对于java字符串敏感,其在replace的写法为\\\ .replaceAll("\\\\", "\").replaceAll("/", "/") .replaceAll("[*]", "*") .replaceAll(":", ":") .replaceAll("[?]", "?") .replaceAll("[|]", "|") // 非必要,但是还是转义吧 .replaceAll("¢", "&cent;").replaceAll("£", "&pound;") .replaceAll("¥", "&yen;").replaceAll("§", "&sect;") .replaceAll("©", "&copy;").replaceAll("®", "&reg;") .replaceAll("×", "&times;").replaceAll("÷", "&divide;"); } else { //避免控制入库导致报错,如果遇到空值,先替换成一个空格 //主要是防止表单验证时,某些浏览器因为兼容性问题,取不到表单某些项的值 return " "; } } // 这里与htmlEncode成轴对称!正如汇编语言,变量的出栈入栈互成对子才能保护现场一样 // 写得我很蛋疼,手工把它反过来了 public static String htmlDecode(String html) { if (html != null) { return html.replaceAll("&divide;", "÷") .replaceAll("&times;", "×") .replaceAll("&reg;", "®") .replaceAll("&copy;", "©") .replaceAll("&sect;", "§") .replaceAll("&yen;", "¥") .replaceAll("&pound;", "£") .replaceAll("&cent;", "¢") // “非必要,但是还是转义吧”部分 .replaceAll("|", "|").replaceAll("?", "?") // 在replace中,在第一个位置要写成[*],在第二个位置就不用这样写 // 因为这里不是正则表达式 .replaceAll(":", ":").replaceAll("*", "*") .replaceAll("/", "/").replaceAll("\", "\\") .replaceAll("-", "-") .replaceAll("+", "+") // “一些可能出现问题的半角符号,还是要转义的。”部分 .replaceAll("&nbsp;", " ").replaceAll("&quot;", "\"") .replaceAll("&gt;", ">").replaceAll("&lt;", "<") .replaceAll("&amp;", "&"); .replaceAll("<script", "&lt;script") // “必要”部分 } else { return null; } } }
这时,再来回顾文章一开头那个问题,如果用户在输入框输入a;drop database;,或者a or 1=1;之类的,执行数据库查询之前,这段字符早变成a;drop& nbsp;database了。
根本就不会再什么sql注入问题了。而一些正常输入的英文、中文字符则完全没有问题。经过Encode与Decode还是原来的样子!