Statement安全漏洞(sql注入问题)
问题展示:
首先我的Mysql数据库中有一张users表,如下图所示
/** * 根据用户名查询用户 * @param username 需要查询的用户名 * @return User 记录对应的JavaBean对象 */ public static User find(String name){ Connection conn = null; Statement sta = null; ResultSet re = null; User user = null; try{ //获取JavaApp与Mysql数据的连接 conn = JDBCUtils.getConnection(); //创建封装SQL语句的对象 sta = conn.createStatement(); //执行sql语句返回结果集合'or true or' String sql = "select id,username,password,email,Date from users where username='"+ name + "'"; re = sta.executeQuery(sql); while(re.next()){ int id = re.getInt("id"); String username = re.getString("username"); String password = re.getString("password"); String email = re.getString("email"); Date d = re.getDate("Date"); user = new User(id,username,password,email,d); } }catch(Exception e){ e.printStackTrace(); throw new RuntimeException("根据用户名查询失败"); }finally{ JDBCUtils.close(re); JDBCUtils.close(sta); JDBCUtils.close(conn); } return user; } public static void main(String[] args) {
//我们查找的是表中已有的数据李四 User user = Demo2_find.find("李四"); System.out.println(user == null ? "查无此人" : "查有此人"); }

运行上面这段代码,程序返回的结果是李四在Mysql数据库确实存在,为了验证测试效果,
这一次,我将上图中标红的部分User user = Demo2_find.find("李四");改为查找王五这个人,大家都知道王五这个人在数据库是不存在的.这次运行的结果为进一步证明,上面的代码是没有问题的,这是我依旧将标红部分的代码改掉,改成User user = Demo2_find.find("'or true or'");这时会发生什么神奇的效果呢?我们运行代码看一下.
为了让大家看的清楚一点,我将整张屏幕截取了下来
我们可以发现,当我们输入'or true or'进行查询的时候竟然通过了,能够查询到Mysql中的数据.
这就是著名的sql注入问题.
产生原因:
因为SQL语句拼接,传入了SQL语句的关键字,绕过了安全检查.
客户端利用JDBC-【Statement】的缺点,传入非法的参数,从而让JDBC返回不合法的值,我们将这种情况下,统称为SQL注入。
解决方案:
使用PreparedStatement对象就可以解决。PreparedStatement对象预处理对象。允许使用占位符对SQL语句中的变量进行占位。对SQL语句进行预先编译。传入SQL语句的关键字,不会被当成关键字而是普通的字符串。包括:程序执行时动态为?符号设置值,安全检查,避免SQL注入问题,预处理能力
select * from user where username = ? and password = ?
Statement与PreparedStatement的区别
现在项目中都不直接用Statement了,而用PreparedStatement。
PreparedStatement它除了具有Statement是所有功能外,
还有动态SQL处理能力,包括:程序执行时动态为?符号设置值,安全检查,避免SQL注入问题,预处理能力。
Statement只能处理静态SQL
1,PreparedStatement既能处理静态SQL,又能处理动态SQL,它继承了Statement的特点
2,站在预处理这个角度来说的:
PreparedStatement【适合】做连续多次相同结构的SQL语句,有优势。
Statement【适合】做连续多次不相同结构的SQL语句,有优势。
适合:是只效率会更高,但并不表示一定要这才样
3,PreparedStatement
1_支持动态SQL,也支持静态SQL
2_预处理
---相同结构的SQL
select id,name from users where id = 1
select id,name,gender from users where id = 2;
是不相同结构
---不同结构的SQL
声明:
静态SQL也可以用PreparedStatement
适合:
静态SQL---优先Statement