最近几天探讨一下关于sql注入的问题,以前林老师也讲过,现在总结一下,
其实,like是会注入的,也不建议用,用占位符实际查询效果不是like本身的意思,相当全匹配。
建议使用instr()函数,本文主要记录一下处理防止注入的源码,为什么用?可以防注入,而拼接的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(x == null)
{
setNull(parameterIndex, 1);
} else
{
checkClosed();
int stringLength = x.length();
if(connection.isNoBackslashEscapesSet())
{
boolean needsHexEscape = isEscapeNeededForString(x, stringLength);
if(!needsHexEscape)
{
byte parameterAsBytes[] = null;
StringBuffer quotedString = new StringBuffer(x.length() + 2);
quotedString.append('\'');
quotedString.append(x);
quotedString.append('\'');
if(!isLoadDataQuery)
parameterAsBytes = StringUtils.getBytes(quotedString.toString(), charConverter, charEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode());
else
parameterAsBytes = quotedString.toString().getBytes();
setInternal(parameterIndex, parameterAsBytes);
} else
{
byte parameterAsBytes[] = null;
if(!isLoadDataQuery)
parameterAsBytes = StringUtils.getBytes(x, charConverter, charEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode());
else
parameterAsBytes = x.getBytes();
setBytes(parameterIndex, parameterAsBytes);
}
return;
}
String parameterAsString = x;
boolean needsQuoted = true;
if(isLoadDataQuery || isEscapeNeededForString(x, stringLength))
{
needsQuoted = false;
StringBuffer buf = new StringBuffer((int)((double)x.length() * 1.1000000000000001D));
buf.append('\'');
for(int i = 0; i < stringLength; i++)
{
char c = x.charAt(i);
switch(c)
{
case 0: // '\0'
buf.append('\\');
buf.append('0');
break;
case 10: // '\n'
buf.append('\\');
buf.append('n');
break;
case 13: // '\r'
buf.append('\\');
buf.append('r');
break;
case 92: // '\\'
buf.append('\\');
buf.append('\\');
break;
case 39: // '\''
buf.append('\\');
buf.append('\'');
break;
case 34: // '"'
if(usingAnsiMode)
buf.append('\\');
buf.append('"');
break;
case 26: // '\032'
buf.append('\\');
buf.append('Z');
break;
default:
buf.append(c);
break;
}
}
buf.append('\'');
parameterAsString = buf.toString();
}
byte parameterAsBytes[] = null;
if(!isLoadDataQuery)
{
if(needsQuoted)
parameterAsBytes = StringUtils.getBytesWrapped(parameterAsString, '\'', '\'', charConverter, charEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode());
else
parameterAsBytes = StringUtils.getBytes(parameterAsString, charConverter, charEncoding, connection.getServerCharacterEncoding(), connection.parserKnowsUnicode());
} else
{
parameterAsBytes = parameterAsString.getBytes();
}
setInternal(parameterIndex, parameterAsBytes);
parameterTypes[(parameterIndex - 1) + getParameterIndexOffset()] = 12;
}
}