sql注入漏洞

PreparedStatement 可以有效防止 sql 注入,PreparedStatement会预编译sql语句,然后再注入参数,这样防止sql拼凑注入。而 Statment 不能防止 sql 注入,它是直接发送执行,因此可以借机拼凑sql语句。

使用Statement发送sql

Login.java
      
      
      
      
  1. package com.cn.statement;
  2. import java.io.BufferedInputStream;
  3. import java.io.BufferedReader;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.InputStreamReader;
  7. import java.sql.Connection;
  8. import java.sql.ResultSet;
  9. import java.sql.Statement;
  10. import java.util.Scanner;
  11. import org.junit.Test;
  12. import com.cn.Util.JdbcUtil;
  13. /**
  14. * 模拟用户登录的效果
  15. * @author liuzhiyong
  16. *
  17. */
  18. public class Login {
  19. //模拟用户输入账号密码
  20. private String name = "木丁西";
  21. private String password = "1234";
  22. /**
  23. * 使用Statement模拟用户登录
  24. * @throws Exception
  25. */
  26. @Test
  27. public void testByStatement() throws Exception {
  28. //创建Scanner对象
  29. Scanner sc = new Scanner(System.in);
  30. System.out.print("请输入用户名:");
  31. name = sc.nextLine();//读取键盘输入
  32. System.out.print("请输入密码:");
  33. password = sc.nextLine();//读取键盘输入
  34. // //创建输入字符流
  35. // BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));//这里用到了输入字节流转换字符流
  36. // System.out.print("请输入用户名:");
  37. // name = keyReader.readLine();//接受键盘输入
  38. // System.out.print("请输入密码:");
  39. // password = keyReader.readLine();//接受键盘输入
  40. Connection conn = null;
  41. Statement stmt = null;
  42. ResultSet rs = null;
  43. try {
  44. //获取连接
  45. conn = JdbcUtil.getConnection();
  46. //获取Statement
  47. stmt = conn.createStatement();
  48. //准备sql
  49. String sql = "select * from users where name = '" + name + "' and password = '" + password+ "'";
  50. //执行sql
  51. rs = stmt.executeQuery(sql);
  52. if(rs.next()){
  53. //登录成功
  54. System.out.println(name + "登录成功!");
  55. }else{
  56. System.out.println("登录失败!");
  57. }
  58. } catch (Exception e) {
  59. e.printStackTrace();
  60. throw new RuntimeException(e);
  61. }finally{
  62. JdbcUtil.close(conn, stmt, rs);
  63. }
  64. }
  65. }
  66. // select * from users where name = 'jkljjljllasf' and password = 'fdasfdsf' or 1='1'
获取Connection连接和释放资源用JdbcUtil.java
       
       
       
       
  1. package com.cn.Util;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7. /**
  8. * jdbc的工具类
  9. * @author liuzhiyong
  10. *
  11. */
  12. public class JdbcUtil {
  13. private static String url = "jdbc:mysql://localhost:3306/mydb";
  14. private static String user = "root";
  15. private static String password = "root";
  16. /**
  17. * 静态代码块(只调用一次)
  18. */
  19. static{
  20. //注册驱动程序
  21. try {
  22. Class.forName("com.mysql.jdbc.Driver");
  23. } catch (ClassNotFoundException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. System.out.println("驱动程序注册出错!");
  27. }
  28. }
  29. /**
  30. * 获取连接对象的方法
  31. */
  32. public static Connection getConnection(){
  33. try {
  34. Connection conn = DriverManager.getConnection(url, user, password);
  35. return conn;
  36. } catch (SQLException e) {
  37. // TODO Auto-generated catch block
  38. e.printStackTrace();
  39. throw new RuntimeException(e);
  40. }
  41. }
  42. /**
  43. * 释放资源的方法
  44. */
  45. public static void close(Connection conn, Statement stmt, ResultSet rs){
  46. //关闭资源(顺序:后打开,先关闭)
  47. if(rs != null){
  48. try {
  49. rs.close();
  50. } catch (SQLException e) {
  51. System.out.println("ResultSet关闭失败!");
  52. throw new RuntimeException(e);
  53. }
  54. }if(stmt != null){
  55. try {
  56. stmt.close();
  57. } catch (SQLException e) {
  58. System.out.println("Statement关闭失败!");
  59. throw new RuntimeException(e);
  60. }
  61. }
  62. if(conn != null){
  63. try {
  64. conn.close();
  65. } catch (SQLException e) {
  66. System.out.println("Connection关闭失败!");
  67. throw new RuntimeException(e);
  68. }
  69. }
  70. }
  71. public static void close(Connection conn, Statement stmt){
  72. //关闭资源(顺序:后打开,先关闭)
  73. if(stmt != null){
  74. try {
  75. stmt.close();
  76. } catch (SQLException e) {
  77. System.out.println("Statement关闭失败!");
  78. throw new RuntimeException(e);
  79. }
  80. }
  81. if(conn != null){
  82. try {
  83. conn.close();
  84. } catch (SQLException e) {
  85. System.out.println("Connection关闭失败!");
  86. throw new RuntimeException(e);
  87. }
  88. }
  89. }
  90. }
用户输入1:
sql注入漏洞_第1张图片
   其实sql注入拼凑成的代码为:  
        
        
        
        
  1. select * from users where name = '随便输入什么内容' and password = '' or '1'='1'

用户输入2:
sql注入漏洞_第2张图片
 其实sql注入拼凑成的代码为: (后面输入的被-- 注释掉了)
       
       
       
       
  1. select * from users where name = '这是随便输入什么也可以不输入' or 1=1 -- ' and password = '这是随便输入什么也可以不输入'

用户输入3: 

其实sql注入拼凑成的代码为:  (后面输入的被-- 注释掉了)
sql注入漏洞_第3张图片
       
       
       
       
  1. select * from users where name = '' or 1=1 -- ' and password = ''

使用PreparedStatement发送sql

       
       
       
       
  1. package com.cn.statement;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.Statement;
  6. import java.util.Scanner;
  7. import org.junit.Test;
  8. import com.cn.Util.JdbcUtil;
  9. /**
  10. * 模拟用户登录的效果
  11. * @author liuzhiyong
  12. *
  13. */
  14. public class Login {
  15. //模拟用户输入账号密码
  16. private String name = "木丁西";
  17. private String password = "1234";
  18. /**
  19. * 使用PreparedStatement模拟用户登录
  20. * @throws Exception
  21. */
  22. @Test
  23. public void testByPrepatedStatement() throws Exception {
  24. //创建Scanner对象
  25. Scanner sc = new Scanner(System.in);
  26. System.out.print("请输入用户名:");
  27. name = sc.nextLine();//读取键盘输入
  28. System.out.print("请输入密码:");
  29. password = sc.nextLine();//读取键盘输入
  30. Connection conn = null;
  31. PreparedStatement pstmt = null;
  32. ResultSet rs = null;
  33. try {
  34. //获取连接
  35. conn = JdbcUtil.getConnection();
  36. //准备sql
  37. String sql = "select * from users where name = ? and password = ?";
  38. //预编译
  39. pstmt = conn.prepareStatement(sql);
  40. //设置参数
  41. pstmt.setString(1, name);
  42. pstmt.setString(2, password);
  43. //执行sql
  44. rs = pstmt.executeQuery();
  45. if(rs.next()){
  46. //登录成功
  47. System.out.println(name + "登录成功!");
  48. }else{
  49. System.out.println("登录失败!");//select * from users where name = '' or 1=1 -- ' and password = ''
  50. }
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. throw new RuntimeException(e);
  54. }finally{
  55. JdbcUtil.close(conn, pstmt, rs);
  56. }
  57. }
  58. }
用户输入:
sql注入漏洞_第4张图片

你可能感兴趣的:(jdbc,MySQL,史上最全的MySQL基础教程)