在《【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还是原来的样子!