1. 程式人生 > >【Javaweb】後臺的字串轉義,入庫之前記得先對字串轉義防止sql注入問題

【Javaweb】後臺的字串轉義,入庫之前記得先對字串轉義防止sql注入問題

在《【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還是原來的樣子!