淺析Statement和PreparedStatement阿纤,SQL注入

一句灌、SQL注入

所謂SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串欠拾,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令胰锌。

上述語句摘自百度百科,可能對于有些人來說晦澀難懂藐窄,那么我舉個(gè)最簡單的例子匕荸,來體驗(yàn)這一過程;

假設(shè)有一個(gè)登錄表單枷邪,后臺數(shù)據(jù)校驗(yàn)sql為select * from user where username = 'XXX' and password = 'XXX',XXX為傳入的用戶名和密碼诺凡,根據(jù)sql返回的結(jié)果判斷登錄是否成功东揣;(方便解釋,簡單處理)

這條sql是預(yù)先拼接好然后提交給數(shù)據(jù)庫執(zhí)行的腹泌,假設(shè)我們把password的內(nèi)容改為1' or '1' = '1嘶卧,注意里面的單引號!如果登錄名為caojiantao凉袱,那么最終生成的sql便是:

select * from user where username = 'caojiantao' and password = '1' or '1' = '1'

=嬉鳌!這樣一來不用知道用戶caojiantao的密碼也能夠登錄成功了专甩,更有甚者钟鸵,在密碼處輸入"1';drop table user;",直接刪除了數(shù)據(jù)表涤躲,十分的危險(xiǎn)棺耍。

這就是一個(gè)最簡單sql注入的例子,輸入包含sql命令的內(nèi)容种樱,欺騙服務(wù)器執(zhí)行破壞數(shù)據(jù)蒙袍。

二俊卤、Statement

JDBC核心接口,對象用于將SQL語句發(fā)送到數(shù)據(jù)庫中害幅。一個(gè)簡單的demo演示Statement的使用消恍;

    public static void main(String[] args) {
        // 數(shù)據(jù)庫配置
        String url = "jdbc:mysql://127.0.0.1/ssm";
        String name = "com.mysql.jdbc.Driver";
        String user = "root";
        String password = "Cjt00382114.";
        // 登錄賬號密碼
        String username = "caojiantao";
        String pwd = "123";
        // 拼接sql
        String sql = "select * from user where username = '" + username + "' and password = '" + pwd + "'";
        try {
            // jdbc操作
            Class.forName(name);
            Connection connection = DriverManager.getConnection(url, user, password);
            // Statement
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(sql);
            while (resultSet.next()){
                System.out.println(resultSet.getString("nickname"));
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }

代碼很簡單,判斷用戶名和密碼是否匹配以现,匹配則輸出用戶的nickname昵稱狠怨;

根據(jù)上面sql注入的問題,我們試著把pwd傳入1' or '1' = '1叼风,前面的1可以隨便填取董,運(yùn)行程序可以發(fā)現(xiàn)輸出了用戶昵稱曹建濤,說明sql注入成功无宿,那么茵汰,我們該怎么避免呢?

三孽鸡、PreparedStatement

采用字符串匹配蹂午?篩選sql命令字符串?沒那么麻煩彬碱,JDBC已經(jīng)有現(xiàn)成的處理方案了豆胸,那就是PreparedStatement

PreparedStatement繼承自Statement巷疼,字面可譯為預(yù)聲明晚胡,強(qiáng)調(diào)一個(gè)預(yù),內(nèi)部包含一個(gè)預(yù)編譯的sql語句嚼沿,參數(shù)采用占位符?進(jìn)行填充估盘,還是看一段代碼體會下;

    public static void main(String[] args) {
        // 數(shù)據(jù)庫配置
        String url = "jdbc:mysql://127.0.0.1/ssm";
        String name = "com.mysql.jdbc.Driver";
        String user = "root";
        String password = "Cjt00382114.";
        // 登錄賬號密碼
        String username = "caojiantao";
        String pwd = "123";
        String preSql = "select * from user where username = ? and password = ?";
        try {
            // jdbc操作
            Class.forName(name);
            Connection connection = DriverManager.getConnection(url, user, password);
            // PreparedStatement
            PreparedStatement preparedStatement = connection.prepareStatement(preSql);
            preparedStatement.setString(1, username);
            preparedStatement.setString(2, pwd);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getString("nickname"));
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }

我們可以修改pwd內(nèi)容為1' or '1' = '1骡尽,運(yùn)行程序沒有任何輸出遣妥,說明PreparedStatement有效地避免了sql注入問題;

因?yàn)镾QL語句在程序運(yùn)行前已經(jīng)進(jìn)行了預(yù)編譯攀细,在程序運(yùn)行時(shí)第一次操作數(shù)據(jù)庫之前箫踩,SQL語句已經(jīng)被數(shù)據(jù)庫分析,編譯和優(yōu)化谭贪,對應(yīng)的執(zhí)行計(jì)劃也會緩存下來并允許數(shù)據(jù)庫已參數(shù)化的形式進(jìn)行查詢境钟,當(dāng)運(yùn)行時(shí)動(dòng)態(tài)地把參數(shù)傳給PreprareStatement時(shí),即使參數(shù)里有敏感字符如 or '1=1'也數(shù)據(jù)庫會作為一個(gè)參數(shù)一個(gè)字段的屬性值來處理而不會作為一個(gè)SQL指令俭识,如此吱韭,就起到了SQL注入的作用了!

上述摘自java中預(yù)處理PrepareStatement為什么能起到防止SQL注入的作用?理盆?6幻骸!

因?yàn)槭抢^承關(guān)系猿规,因而Statement具備的PreparedStatement全都有衷快,而且PreparedStatement還具備獨(dú)有的預(yù)處理功能,相比Statement姨俩,PreparedStatement好處有三:

  1. 提高代碼的可讀性蘸拔,便于維護(hù);
  2. 提高了sql執(zhí)行效率环葵;
  3. 增強(qiáng)了安全性调窍,避免sql注入;

四张遭、花絮——myBatis的 # 和 $

# 相當(dāng)于對數(shù)據(jù) 加上 雙引號邓萨,$ 相當(dāng)于直接顯示數(shù)據(jù)。

一句話言簡意賅菊卷。分條陳述:

  1. # 能夠sql注入問題缔恳,$ 不行;
  2. $ 用于傳入數(shù)據(jù)庫對象洁闰,例如表名歉甚;
  3. 能用 # 就不要使用 $;

參考文章:mybatis中的#和$的區(qū)別

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扑眉,一起剝皮案震驚了整個(gè)濱河市纸泄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌腰素,老刑警劉巖聘裁,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異耸弄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)卓缰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門计呈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人征唬,你說我怎么就攤上這事捌显。” “怎么了总寒?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵扶歪,是天一觀的道長。 經(jīng)常有香客問我,道長善镰,這世上最難降的妖魔是什么妹萨? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮炫欺,結(jié)果婚禮上乎完,老公的妹妹穿的比我還像新娘。我一直安慰自己品洛,他們只是感情好树姨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桥状,像睡著了一般帽揪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辅斟,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天转晰,我揣著相機(jī)與錄音,去河邊找鬼砾肺。 笑死挽霉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的变汪。 我是一名探鬼主播侠坎,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼裙盾!你這毒婦竟也來了实胸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤番官,失蹤者是張志新(化名)和其女友劉穎庐完,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徘熔,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡门躯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酷师。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讶凉。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖山孔,靈堂內(nèi)的尸體忽然破棺而出懂讯,到底是詐尸還是另有隱情,我是刑警寧澤台颠,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布褐望,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏瘫里。R本人自食惡果不足惜实蔽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望减宣。 院中可真熱鬧盐须,春花似錦、人聲如沸漆腌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闷尿。三九已至塑径,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間填具,已是汗流浹背统舀。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劳景,地道東北人誉简。 一個(gè)月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像盟广,于是被迫代替她去往敵國和親闷串。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis 筋量? MyBatis 是支持定制化 SQL烹吵、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,520評論 0 4
  • JDBC簡介 SUN公司為了簡化、統(tǒng)一對數(shù)據(jù)庫的操作桨武,定義了一套Java操作數(shù)據(jù)庫的規(guī)范肋拔,稱之為JDBC。JDBC...
    奮斗的老王閱讀 1,518評論 0 51
  • 概念Java提供了 Statement呀酸、PreparedStatement 和 CallableStatement...
    Gothrow閱讀 1,846評論 0 1
  • 前奏:“有空的時(shí)候用元認(rèn)知梳理自己建立信心的過程凉蜂,這是有‘套路’的,也就是說有思維模型和相應(yīng)的行動(dòng)套路在里面性誉×裕”這...
    謝宇雨閱讀 198評論 2 0
  • 白牛鎮(zhèn)高年級數(shù)學(xué)教研會發(fā)言1劉教授:解決老大難的問題,來和鄉(xiāng)小的學(xué)生來共同探討探討這個(gè)老大難的問題艾栋。以四則運(yùn)算為總...
    c劉春雨閱讀 410評論 0 0