学过编程的人都基本知道sql注入问题,废话不多说,直接进入代码部分,代码注释已经够详细了,此处不罗嗦!
1 package edu.test; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.sql.Statement; 8 import java.util.Iterator; 9 10 11 12 /** 13 * @author lzj 14 * @create 2017年11月14日 下午7:54:34 15 * @describe 16 */ 17 public class TestJdbc { 18 19 /** 20 * at 2017年11月14日 下午7:54:34 by lzj 21 * @Parameters1 22 * @Returns void 23 */ 24 public static void main(String[] args) { 25 Connection conn = null; 26 // TODO Auto-generated method stub 27 try { 28 //mysql -hlocalhost -uroot -plzj_aeon+ 29 Class.forName("com.mysql.jdbc.Driver"); 30 long start=System.currentTimeMillis(); 31 //此处数据库建立远程连接(内部采用socket建立远程连接)比较耗时、一般开发中我们采用连接池方式、此处只是为了简单的一个示例 32 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "lzj_aeon+"); 33 long end=System.currentTimeMillis(); 34 System.out.println(conn); 35 System.out.println("数据库建立连接耗时:"+(end-start)+"毫秒!"); 36 Statement smt= conn.createStatement(); 37 /* 38 * 此处参数id是从外部传入,如果懂得sql注入原理的人会通过传入 xxx or 1=1进行恶意sql的注入 39 * 还有 xxx or 1=1; drop table xxx;....此处不一一列举只要能执行的sql语句都可以执行 40 * 删表、删库、truncate table xxx;此处只模拟其中一种!通过暴库获得数据库以及库内所有的表名,然后进行恶意SQL注入 41 * 此处or前面可以任意输入,因为后面条件1=1已经获得了该SQL的执行权 42 * */ 43 String id="1 or 1=1"; //例如此处:1 or 1=1 是黑客注入的恶意SQL,然后我们执行它,看看会是什么结果 44 String sql="delete from student where id = "+id; 45 smt.execute(sql); 46 } catch (ClassNotFoundException e) { 47 e.printStackTrace(); 48 } catch (SQLException e) { 49 e.printStackTrace(); 50 }finally{ 51 try { 52 if(conn!=null) conn.close(); 53 } catch (SQLException e) { 54 // TODO Auto-generated catch block 55 e.printStackTrace(); 56 } 57 58 } 59 60 } 61 62 }
结果:
此处通过注入的恶意代码1 or 1=1,将该数据库中所有的数据都删完了!
为了解决sql注入引发的问题,我们在实际开发当中引入了prepareStatment(预编译的sql语句),直接进入代码部分:
1 package edu.test; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.sql.Statement; 9 import java.util.Iterator; 10 11 12 13 /** 14 * @author lzj 15 * @create 2017年11月14日 下午7:54:34 16 * @describe 17 */ 18 public class TestJdbc { 19 20 /** 21 * at 2017年11月14日 下午7:54:34 by lzj 22 * @Parameters1 23 * @Returns void 24 */ 25 public static void main(String[] args) { 26 Connection conn = null; 27 // TODO Auto-generated method stub 28 try { 29 //mysql -hlocalhost -uroot -plzj_aeon+ 30 Class.forName("com.mysql.jdbc.Driver"); 31 long start=System.currentTimeMillis(); 32 //此处数据库建立远程连接(内部采用socket建立远程连接)比较耗时、一般开发中我们采用连接池方式、此处只是为了简单的一个示例 33 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "lzj_aeon+"); 34 long end=System.currentTimeMillis(); 35 System.out.println(conn); 36 System.out.println("数据库建立连接耗时:"+(end-start)+"毫秒!"); 37 /*Statement smt= conn.createStatement(); 38 39 * 此处参数name是从外部传入,如果懂得sql注入原理的人会通过传入 xxx or 1=1进行恶意sql的注入 40 * 还有 xxx or 1=1; drop table xxx;....此处不一一列举只要能执行的sql语句都可以执行 41 * 删表、删库、truncate table xxx;此处只模拟其中一种!通过暴库获得数据库以及库内所有的表名,然后进行恶意SQL注入 42 * 此处or前面可以任意输入,因为后面条件1=1已经获得了该SQL的执行权 43 * 44 String id="1 or 1=1"; //例如此处:1 or 1=1 是黑客注入的恶意SQL,然后我们执行它,看看会是什么结果 45 String sql="delete from student where id = "+id;*/ 46 String sql="insert into student (id,name) values (?,?)"; 47 PreparedStatement ps=conn.prepareStatement(sql); 48 ps.setInt(1, 1); 49 ps.setString(2, "lzj"); 50 ps.execute(); 51 } catch (ClassNotFoundException e) { 52 e.printStackTrace(); 53 } catch (SQLException e) { 54 e.printStackTrace(); 55 }finally{ 56 try { 57 if(conn!=null) conn.close(); 58 } catch (SQLException e) { 59 // TODO Auto-generated catch block 60 e.printStackTrace(); 61 } 62 63 } 64 65 } 66 67 }
JDBC查询结果集处理:
1 package edu.test; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.sql.Statement; 9 import java.util.Iterator; 10 11 12 13 /** 14 * @author lzj 15 * @create 2017年11月14日 下午7:54:34 16 * @describe 17 */ 18 public class TestJdbc { 19 20 /** 21 * at 2017年11月14日 下午7:54:34 by lzj 22 * @Parameters1 23 * @Returns void 24 */ 25 public static void main(String[] args) { 26 Connection conn = null; 27 PreparedStatement ps=null; 28 ResultSet rs=null; 29 // TODO Auto-generated method stub 30 try { 31 //mysql -hlocalhost -uroot -plzj_aeon+ 32 Class.forName("com.mysql.jdbc.Driver"); 33 long start=System.currentTimeMillis(); 34 //此处数据库建立远程连接(内部采用socket建立远程连接)比较耗时、一般开发中我们采用连接池方式、此处只是为了简单的一个示例 35 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "lzj_aeon+"); 36 long end=System.currentTimeMillis(); 37 System.out.println(conn); 38 System.out.println("数据库建立连接耗时:"+(end-start)+"毫秒!"); 39 /*Statement smt= conn.createStatement(); 40 41 * 此处参数name是从外部传入,如果懂得sql注入原理的人会通过传入 xxx or 1=1进行恶意sql的注入 42 * 还有 xxx or 1=1; drop table xxx;....此处不一一列举只要能执行的sql语句都可以执行 43 * 删表、删库、truncate table xxx;此处只模拟其中一种!通过暴库获得数据库以及库内所有的表名,然后进行恶意SQL注入 44 * 此处or前面可以任意输入,因为后面条件1=1已经获得了该SQL的执行权 45 * 46 String id="1 or 1=1"; //例如此处:1 or 1=1 是黑客注入的恶意SQL,然后我们执行它,看看会是什么结果 47 String sql="delete from student where id = "+id;*/ 48 String sql="select id,name from student where id>?"; //将id>1的学生取出来 49 ps=conn.prepareStatement(sql); 50 ps.setInt(1, 1); 51 /*ps.setInt(1, 2); 52 ps.setString(2, "lzj1");*/ 53 rs=ps.executeQuery(); 54 while(rs.next()) {//此处采用游标方式 55 System.out.println(rs.getInt(1)+"---"+rs.getString(2)); //此处getxxx(index)其中index代表列索引 56 } 57 } catch (ClassNotFoundException e) { 58 e.printStackTrace(); 59 } catch (SQLException e) { 60 e.printStackTrace(); 61 }finally{ 62 try { 63 if(rs!=null) { 64 rs.close(); 65 } 66 } catch (Exception e1) { 67 System.out.println("rs流关闭异常!"); 68 e1.printStackTrace(); 69 } 70 try { 71 if(ps!=null) { 72 ps.close(); 73 } 74 } catch (Exception e2) { 75 System.out.println("ps流关闭异常!"); 76 e2.printStackTrace(); 77 } 78 try { 79 if(conn!=null) { conn.close();} 80 } catch (SQLException e3) { 81 // TODO Auto-generated catch block
System.out.println("conn流关闭异常!");
82 e3.printStackTrace(); 83 } 84 85 86 } 87 88 } 89 90 }
ps.setObj(index,value);-- 通用
此处代码流关闭代码简单并且繁琐,所以省略!关闭顺序必须遵循resultSet--->statament(prepareStatemet)--->connection且每种流关闭异常分开写!