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