造成SQL注入攻击的根本原因在于攻击者可以改变SQL查询的上下文,使程序员原本要作为数据解析的数值,被篡改为命令了。防止SQL注入的方法如下:
正确使用参数化API进行SQL查询。
如果构造SQL指令时需要动态加入约束条件,可以通过创建一份合法字符串列表,使其对应于可能要加入到SQL指令中的不同元素,来避免SQL注入攻击。
避免出现一些详细的错误消息,防止攻击者利用报错信息来判断后台SQL的拼接形式,甚至是直接利用这些报错注入将数据库中的数据通过报错消息显示出来。
例如:以下代码片段使用java.sql.PreparedStatement代替java.sql.Statement,在java.sql.PreparedStatement类中可以对输入字符串进行转义,如果使用正确的话,可以防止SQL注入。
public void doPrivilegedAction(HttpServletRequest request, char[] password) throws SQLException {
Connection connection = getConnection();
if (connection == null) {
// handle error
}
try {
String username = request.getParameter("username");
String pwd = hashPassword(password);
// Ensure that the length of user name is legitimate
if ((username.length() > 8) {
// Handle error
}
String sqlString = "select * from db_user where username=? and password=?";
PreparedStatement stmt = connection.prepareStatement(sqlString);
stmt.setString(1, username);
stmt.setString(2, pwd);
ResultSet rs = stmt.executeQuery();
if (!rs.next()) {
throw new SecurityException("User name or password incorrect");
}
// Authenticated, proceed
} finally {
try {
connection.close();
} catch (SQLException x) {
// forward to handler
}
}
}