【JDBC】封装实现及 PreparedStatement防止sql注入问题的应用

本文介绍了如何使用Java的JDBC连接MySQL数据库,包括在src目录下创建db.properties文件存储配置,创建JdbcUtils工具类进行数据库连接的封装。同时,文章讨论了SQL注入问题及其危害,并展示了PreparedStatement如何防止SQL注入,提高了SQL执行效率。通过使用PreparedStatement,可以更安全、高效地执行SQL操作。
摘要由CSDN通过智能技术生成

封装

1. 在src目录下创建一个db.properties文件

driver=com.mysql.jdbc.Driver 
url=jdbc:mysql://localhost:3306/jdbcStudy? useUnicode=true&characterEncoding=utf8&useSSL=true 
username=root 
password=123456

2. 下新建一个 utils 包,新建一个类 JdbcUtils

public class JdbcUtils { 
private static String driver = null; 
private static String url = null; 
private static String username = null; 
private static String password = null; static{ 
    try{
    //读取db.properties文件中的数据库连接信息
    //此处涉及反射的类加载器和map子接口properties类的知识
     InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); 
     Properties prop = new Properties();  
     prop.load(in); 
     //获取数据库连接驱动 
     driver = prop.getProperty("driver"); 
     //获取数据库连接URL地址 
     url = prop.getProperty("url"); 
     //获取数据库连接用户名 
     username = prop.getProperty("username");
     //获取数据库连接密码 
     password = prop.getProperty("password"); 
     //加载数据库驱动
      Class.forName(driver); 
      }catch (Exception e) { 
      throw new ExceptionInInitializerError(e); 
    } 
 }
 // 获取数据库连接对象
  public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(url, username,password); 
   }
   // 释放资源,要释放的资源包括Connection数据库连接对象,存储查询结果的ResultSet对象 
   public static void release(Connection conn,Statement st,ResultSet rs){ 
   if(rs!=null){ 
      try{
   //关闭存储查询结果的ResultSet对象
       rs.close(); 
      }catch (Exception e) { 
        e.printStackTrace(); 
     }
        rs = null;
    }
    if(st!=null){
       try{
       //关闭负责执行SQL命令的Statement对象
        st.close();
         }catch (Exception e) { 
         e.printStackTrace(); 
         } }if(conn!=null){ 
         try{
         //关闭Connection数据库连接对象 
         conn.close();
          }catch (Exception e) { 
          e.printStackTrace();
           } 
         }
       }
    }

3.封装好后,插入一条数据(删改查同理)

public class TestInsert { 
public static void main(String[] args) { 
  Connection conn = null; 
  Statement st = null;
  ResultSet rs = null; 
   try{
	 //获取一个数据库连接
	  conn = JdbcUtils.getConnection(); 
	  //通过conn对象获取负责执行SQL命令的Statement对象
	   st = conn.createStatement(); 
	   //要执行的SQL命令 
	   String sql = "insert into users(id,name,password,email,birthday) " + "values(4,'kuangshen','123','24736743@qq.com','2020-01- 01')"; 
	   //执行插入操作,executeUpdate方法返回成功的条数 
	   int num = st.executeUpdate(sql); 
	   if(num>0){
	    System.out.println("插入成功!!");
	     }
	   }catch (Exception e) { 
	      e.printStackTrace();
	   }finally{
	        //SQL执行完成之后释放相关资源
	         JdbcUtils.release(conn, st, rs); 
	        } 
	    } 
    }

SQL 注入问题

通过巧妙的技巧来拼接字符串,造成SQL短路,从而获取数据库数据。

public static void main(String[] args) {
login("zhangsan","123456"); // 正常登陆 
login("'or '1=1","'or '1=1"); // SQL 注入 }

 //查询语句
 String sql = "select * from users where name='"+username+"' and password='"+password+"'";
//注入示例,条件变为永真
 select * from users where name='' or '1=1' and password = ''or '1=1' "

PreparedStatement对象

  1. PreperedStatement是Statement的子类,它的实例对象可以通过调用Connection.preparedStatement()方法获得。

  2. PreperedStatement可以避免SQL注入的问题。

  3. PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。

  4. PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。

一、 插入数据

public class TestInsert { 
public static void main(String[] args) { 
	Connection conn = null; 
	PreparedStatement st = null; 
	ResultSet rs = null; 
		try{
		//获取一个数据库连接 
		  conn = JdbcUtils.getConnection();
		 //要执行的SQL命令,SQL中的参数使用?作为占位符 
		  String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)"; 
		 //通过conn对象获取负责执行SQL命令的prepareStatement对象
		  st = conn.prepareStatement(sql); 
		  //为SQL语句中的参数赋值,注意,索引是从1开始的 
		  st.setInt(1, 4);
		  //id是int类型的 
		  st.setString(2, "ha");
		  //name是varchar(字符串类型) 
		  st.setString(3, "123");
		  //password是varchar(字符串类型) 
		  st.setString(4, "234@qq.com");
		  //email是varchar(字符串类型) 
		  st.setDate(5, new java.sql.Date(new Date().getTime()));
		  //birthday是date类型 
		  //执行插入操作,executeUpdate方法返回成功的条数 
		  int num = st.executeUpdate();
		   if(num>0){ 
		   System.out.println("插入成功!!");
	   }catch (Exception e) {
	   		 e.printStackTrace(); 
	   }finally{ 
	   //SQL执行完成之后释放相关资源 
	   JdbcUtils.release(conn, st, rs);
	    } 
	}
}

避免注入原理:执行的时候参数会用引号包起来,并把参数中的引号作为转义字符,从而避免了参数也作为条件的一部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值