像这样的陈述
String query = "SELECT * FROM users WHERE userid ='"+ userid + "'" + " AND password='" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);符合SQL注入的条件。但是,PreparedStatement如何帮助防止SQL注入?考虑以下情况:
PreparedStatement stmt = connection.prepareStatement("SELECT * FROM users WHERE userid=? AND password=?");
stmt.setString(1, userid);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();如果有人进入userId = "abc"和password = "1=1",因为这也将被视为有效字符串.
发布于 2014-07-29 21:04:31
保护您的确切方式取决于数据库,但是有两个明显的选项:
在我看来,后者是一个更明智的解决方案,因为它允许数据库缓存查询计划,承认两个查询与参数值完全相同。我希望任何现代数据库都能在其本机通信协议中支持这一点。
发布于 2014-07-29 22:22:09
String query = "SELECT * FROM users WHERE userid ='"+ userid + "'" + " AND password='" + password + "'";在这里,如果您试图演示sql注入,密码的值可能类似于:‘OR 1=1 OR ''='
然后将发送到DB服务器执行的结果SQL为-
SELECT * FROM users WHERE userid ='abc' AND password='' OR 1=1 OR ''=''因此,它从表中选择所有条目,而不管用户名和密码如何,因为userid ='abc‘和=’OR,1=1‘=’‘都是真的。任何未经授权的人都可以访问所有用户的数据。
如第二条语句使用参数化准备语句-
它将使用userid = "abc“和密码=”‘OR 1=1 OR’=‘’搜索表中的条目。
由于准备好的语句是在DB服务器中预编译的,也就是说,首先,空白查询从用户选择* userid=在哪里?然后将password=?发送到服务器,服务器将对其进行编译,然后将数据(参数)单独发送到db (执行时)。数据,即密码= ‘OR 1=1 OR’‘=’‘由JDBC驱动程序作为字符串文本发送。然后DB服务器强制将其用作有效参数,而不是sql查询。
发布于 2014-07-29 21:02:23
关于第二个例子,
PreparedStatement stmt =connection.prepareStatement(“从用户中选择*”+“userid=?和password=?");stmt.setString(1,用户rs );stmt.setString(2,密码);ResultSet rs= stmt.executeQuery(); 如果有人输入userId = "abc“和密码= "1=1",因为这也将被视为有效字符串.
答案是肯定的,但是一个正确转义的字符串文字。因此,密码必须是1=1才能工作。要明确的是,它不受SQL注入的限制,因为这些变量是正确绑定的。
根据PreparedStatement.setString(int, String) Javadoc粗体加,
将指定的参数设置为给定的Java字符串值。驱动程序将其转换为LONGVARCHAR或LONGVARCHAR值(取决于参数相对于驱动程序对VARCHAR值的限制的大小)。
https://stackoverflow.com/questions/25024894
复制相似问题