目录

JDBC的简单使用

向JDBC注入攻击

防止注入攻击

自建JDBC工具类

自建工具类优化--使用配置文件

使用数据库连接池优化工具类

JDBC的简单使用

 package Test;

 import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; /*JDBCsun公司提供的一套标准数据库操作规范
* JDBC使用步骤
* 1 注册驱动--告诉JVM使用的是哪一个数据库
* 2 获得连接--使用JDBC中的类完成对MySQL数据库的连接
* 3 获得语句执行平台--通过连接对象获取SQL语句1的执行者对象
* 4 执行sql语句--使用执行者对象向数据库执行SQL语句,并获取执行后的结果
* 5 处理结果
* 6 释放资源
* ----------在使用之前一定要先导入jar包
*/ public class Main{
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1 注册驱动,但查看源码发现这样会注册两次
//DriverManager.registerDriver(new Driver());
//使用反射技术注册,在这里类名可能找不到因此抛出类名查不到的异常
Class.forName("com.mysql.jdbc.Driver"); //2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
//连接,可能连接不到抛出SQL异常
Connection con =DriverManager.getConnection(url, username,password); //3 获得语句执行平台,通过数据库连接对象获得SQL语句的执行者对象,注意导包为sql的包
Statement stat=con.createStatement();
//查询语句
String sql ="Select * from titles"; //4 调用执行者对象方法,执行SQL语句获取结果集
ResultSet rs=stat.executeQuery(sql);
//5 处理结果集
while(rs.next()){
System.out.println(rs.getString("emp_no")+" "+rs.getString("title"));
} //6 释放资源
rs.close();
stat.close();
con.close();
}
}

向JDBC注入攻击

创建数据表

 CREATE TABLE users(
username VARCHAR(20),
PASSWORD VARCHAR(10)
); INSERT INTO users VALUES('a',''),('b','');

待注入攻击的代码:

 package Test;

 import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner; /*MySQL注入攻击
* 用户登录案例
*/ public class Main{
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver"); //2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
Connection con =DriverManager.getConnection(url, username,password);
Statement stat=con.createStatement();
//查询语句
Scanner sc=new Scanner(System.in);
String user=sc.next();
String pass=sc.next();
String sql ="Select * from users where username= '"+user+"' and password= '"+pass+"'"; //4 调用执行者对象方法,执行SQL语句获取结果集
ResultSet rs=stat.executeQuery(sql);
System.out.println(sql);
//5 处理结果集
while(rs.next()){
System.out.println(rs.getString("username")+" "+rs.getString("password"));
} //6 释放资源
rs.close();
stat.close();
con.close();
}
}

 代码运行结果:

攻击的原理:

利用SQL语句:Select * from users where username= 'a' and password= '1'or'1=1',这样由于最后一个是或运算那么就会显示出来所有的数据,因此在输入时只要想办法凑成这样的形式就可以了。

输入:aa 12'or'1=1  这样便可以完成攻击,即使输入的用户名不对也可以正常登陆。

防止注入攻击

 package Test;

 import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner; /*MySQL防止注入攻击--采用statement的子类preparedstatement
* 还可以用占位符实现增删改查等操作
*/ public class Main{
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver"); //2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
Connection con =DriverManager.getConnection(url, username,password); //查询语句
Scanner sc=new Scanner(System.in);
String user=sc.next();
String pass=sc.next();
//用?占位符代替参数
String sql ="Select * from users where username=? and password= ?";
PreparedStatement pds=con.prepareStatement(sql);
pds.setObject(1, user);
pds.setObject(2, pass);
//4 调用执行者对象方法,执行SQL语句获取结果集
ResultSet rs=pds.executeQuery();
System.out.println(sql);
//5 处理结果集
while(rs.next()){
System.out.println(rs.getString("username")+" "+rs.getString("password"));
} //6 释放资源
rs.close();
pds.close();
con.close();
}
}

自建JDBC工具类

JDBCUtils.class文件

 package Test;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; public class JDBCUtils {
private JDBCUtils(){}
private static Connection con; static{
try {
Class.forName("com.mysql.jdbc.Driver");
//2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
con =DriverManager.getConnection(url, username,password);
} catch (Exception e) {
throw new RuntimeException(e+"数据库连接失败!");
}
}
//定义静态方法,返回数据库的连接对象
public static Connection getConnection(){
return con;
} //释放资源
public static void close(Connection con,Statement stat){
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//重载,关闭结果集
public static void close(Connection con,Statement stat,ResultSet rs){
//注意释放的顺序
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

测试代码:

 package Test;

 import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import Test.JDBCUtils; public class JDBCTset {
public static void main(String[] args) throws SQLException {
Connection con =JDBCUtils.getConnection();
PreparedStatement pst=con.prepareStatement("SELECT * FROM titles");
ResultSet rs =pst.executeQuery();
while(rs.next()){
System.out.println(rs.getString("title"));
}
//释放资源
JDBCUtils.close(con, pst);
}
}

自建工具类优化--使用配置文件

优化代码

 package Test;

 import java.io.IOException;
import java.io.InputStream; /*在前面的代码中由于数据库用户名,密码直接在静态代码块中,相当于写死了代码,不容易修改
* 因此采用properties配置文件,方便后期维护。配置文件建议放在src下,方便自动拷贝bin目录下
*
*/ import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; public class JDBCUtils {
private JDBCUtils(){}
private static Connection con;
private static String driverClass;
private static String url;
private static String username;
private static String password;
//放到静态代码块中保证读取配置文件,获取连接只执行一次
static{
try{
readConfig();
//反射
Class.forName(driverClass);
con=DriverManager.getConnection(url,username,password);
}catch(Exception e){
throw new RuntimeException("数据库连接失败!");
} } private static void readConfig() throws IOException{
//通过字节流,使用类加载器读取配置文件的内容
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("database.properties");
Properties pro = new Properties();
pro.load(in);
driverClass=pro.getProperty("driverClass");
url = pro.getProperty("url");
username=pro.getProperty("username");
password=pro.getProperty("password");
} //定义静态方法,返回数据库的连接对象
public static Connection getConnection(){
return con;
} //释放资源
public static void close(Connection con,Statement stat){
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//重载,关闭结果集
public static void close(Connection con,Statement stat,ResultSet rs){
//注意释放的顺序
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

测试代码

 package Test;

 import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import Test.JDBCUtils; public class JDBCTset {
public static void main(String[] args) throws SQLException {
Connection con =JDBCUtils.getConnection();
//当能输出数据库连接时边说用工具类正常了
System.out.println(con);
//由于是简单的测试,因此不用释放资源
//JDBCUtils.close(con, pst);
}
}

使用数据库连接池优化工具类

优化代码:

 package Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties; import javax.sql.DataSource; /*
* JDBC连接池工具类,使用连接池专门负责数据库的连接
* JDBC连接池简化了sql语句中的增删改查操作,方便代码编写
*/
import org.apache.commons.dbcp.BasicDataSource; public class JDBCUtils {
private JDBCUtils(){}
private static String driverClass;
private static String url;
private static String username;
private static String password;
private static BasicDataSource datasource =new BasicDataSource();
//放到静态代码块中保证读取配置文件,获取连接只执行一次
static{
try {
readConfig();
//数据库连接配置
datasource.setDriverClassName(driverClass);
datasource.setUrl(url);
datasource.setUsername(username);
datasource.setPassword(password);
//对象连接池中的数量配置,这些配置可以不用配置的
datasource.setInitialSize(10);//初始化的连接数
datasource.setMaxActive(8);//最大连接数
datasource.setMaxIdle(5);//最大空闲数
datasource.setMinIdle(1);//最小空闲数
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} private static void readConfig() throws IOException{
//通过字节流,使用类加载器读取配置文件的内容
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("database.properties");
Properties pro = new Properties();
pro.load(in);
driverClass=pro.getProperty("driverClass");
url = pro.getProperty("url");
username=pro.getProperty("username");
password=pro.getProperty("password");
} //定义静态方法,返回数据库的连接对象
public static DataSource getDataSource(){
return datasource;
}
}

测试代码:

 package Test;

 import java.sql.SQLException;
import java.util.List; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler; public class JDBCTset {
private static QueryRunner qr=new QueryRunner(JDBCUtils.getDataSource()); public static void main(String[] args) throws SQLException {
String sql="select * from titles";
//ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。这是dbutils所特有的
List<Object[]> list =qr.query(sql, new ArrayListHandler());
for(Object[] objs:list){
for(Object obj:objs)
System.out.print(obj+"\t\t");
System.out.println();
}
} }

0

最新文章

  1. atitit.提升2--3倍开发效率--cbb体系的建设..
  2. [Solution] Microsoft Windows 服务(3) 使用Quartz.net定时任务
  3. Spring(五)AOP简述
  4. Config The Image URL Solution
  5. 【Android 界面效果42】如何自定义字体
  6. php5 图片验证码一例
  7. SQL 两张结构一样的表合并查询 .
  8. html5时间选择器
  9. Visual Studio 命中断点时 打印信息
  10. Opencv2.4.4作图像旋转和缩放
  11. redis(1)
  12. 【LSGDOJ 1351】关灯
  13. 【JVM系列】一步步解析java执行内幕
  14. Shell-删除误解压的文件
  15. 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第5章编程练习1
  16. Redis 教程 Java工程师学习知识点
  17. cf水题
  18. 计划评审技术PERT
  19. Ultra-QuickSort---poj2299 (归并排序.逆序数.树状数组.离散化)
  20. Hadoop之MapReduce学习笔记(二)

热门文章

  1. javascript当中类型转换,typeof的用法
  2. 【LOJ】#3051. 「十二省联考 2019」皮配
  3. springboot集成mongoDB简易使用
  4. MySQL自测测试
  5. NodeJS express框架的使用
  6. 关于小程序去除view/navigator 点击后默认阴影效果
  7. react快速上手一(使用js语法,创建虚拟DOM元素)
  8. MUI 结合layui实现分页
  9. C++ STL 之 函数对象
  10. 基于Vue实现拖拽效果