為什么占位符可以防止sql注入?


先看下面用占位符來查詢的一句話

String sql = "select * from administrator where adminname=?";
psm = con.prepareStatement(sql);

String s_name ="zhangsan' or '1'='1";
psm.setString(1, s_name);

假設數據庫表中並沒有zhangsan這個用戶名,

用plsql運行sql語句,可以查出來所有的用戶名,但是在Java中並沒有查出任何數據,這是為什么呢?

首先,setString()的源碼中只有方法名字,並沒有任何過程性處理,

那么答案肯定出現在Java到數據庫這個過程中,也就是mysql和oracle驅動包中,在mysql驅動包中,PreparedStatement繼承並實現了jdk中的setString方法,

也就是原因在於數據庫廠商幫你解決了這個問題,下面就看看這個方法的具體實現:

public void setString(int parameterIndex, String x) throws SQLException { // if the passed string is null, then set this column to null
        if (x == null) { setNull(parameterIndex, Types.CHAR); } else { StringBuffer buf = new StringBuffer((int) (x.length() * 1.1)); buf.append('\''); int stringLength = x.length(); //
            // Note: buf.append(char) is _faster_ than // appending in blocks, because the block // append requires a System.arraycopy().... // go figure... //             for (int i = 0; i < stringLength; ++i) { char c = x.charAt(i); switch (c) { case 0: /* Must be escaped for 'mysql' */ buf.append('\\'); buf.append('0'); break; case '\n': /* Must be escaped for logs */ buf.append('\\'); buf.append('n'); break; case '\r': buf.append('\\'); buf.append('r'); break; case '\\': buf.append('\\'); buf.append('\\'); break; case '\'': buf.append('\\'); buf.append('\''); break; case '"': /* Better safe than sorry */
                    if (this.usingAnsiMode) { buf.append('\\'); } buf.append('"'); break; case '\032': /* This gives problems on Win32 */ buf.append('\\'); buf.append('Z'); break; default: buf.append(c); } } buf.append('\''); String parameterAsString = buf.toString(); byte[] parameterAsBytes = null; if (!this.isLoadDataQuery) { parameterAsBytes = StringUtils.getBytes(parameterAsString, this.charConverter, this.charEncoding, this.connection .getServerCharacterEncoding(), this.connection .parserKnowsUnicode()); } else { // Send with platform character encoding
                parameterAsBytes = parameterAsString.getBytes(); } setInternal(parameterIndex, parameterAsBytes); } }

所以轉義后的sql為'zhangsan\' or \'1\'=\'1';這個時候是查不出來的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM