【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》(
注意:如下程式碼的&都用全形表示了,應該使用半形的,但是半形的&會被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還是原來的樣子!