为什么占位符可以防止sql注入?
Posted GreatAnt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么占位符可以防止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\';这个时候是查不出来的。
以上是关于为什么占位符可以防止sql注入?的主要内容,如果未能解决你的问题,请参考以下文章