目录
六、使用PreparedStatement来解决sql注入的问题
一、JDBC的概念
JDBC(Java DataBase Connectivity, java数据库连接)是一种用于执行SQL语句的Java API (简而言之 使用JAVA语言 让SQL在MySQL中执行),可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。
JDBC下载(百度MySQL驱动)
Java属于什么语言? ---- OOP面向对象的语言
数据库属于什么语言? ----SQL语言:结构化查询语言
上面会因为语言不同,带来沟通问题?
如果是你如何解决java和数据库之间的沟通? -- 找个翻译官
二、Java连接MySQL数据库
步骤一:创建一个Java工程
步骤二:在工程下创建一个目录lib ---->放jar的
步骤三:把该jar进行解压---->一定要在程序中完成
写程序
//加载驱动 //方法的参数是驱动的jar包中的一个驱动类名 Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接对象 Connection conn = DriverManager.getConnection("jdbc:数据标识://ip:端口号/数据库名","账号","密码");//创建Statement //执行SQL语句 Statement sta = conn.createStatement();//执行sql语句 增删改 st.executeUpdate(sql);
三、增删改功能
public class Test01 {
public static void main(String[] args)throws Exception {
//1.加载驱动---理解为引用翻译
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接对象
// String url, 数据库的路径 mysql5.7以后
// 协议:数据的种类://ip:端口号/数据库名?serverTimezone=Asia/Shanghai
// jdbc:mysql://
// String user,账号
// String password 密码
String url="jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai";
String user="root";
String password="root";
Connection connection= DriverManager.getConnection(url,user,password);
//3.获取执行sql语句的对象。
Statement statement=connection.createStatement();
//4.执行sql语句。增删改
String sql="delete from t_student where id=1";
statement.executeUpdate(sql);
}
}
总结 :
1. 加载驱动 Class.forName("com.mysql.cj.jdbc.Driver");
2. 获取连接对象 Connection connection=DriverManager.getConnection(url,u,pass);
3. 获取执行sql语句的对象. Statement statement=connection.createStatement();
4. 执行sql语句: statement.executeUpdate(sql);
public class TestJdbc {
//测试添加功能---往数据库中添加
@Test
public void testInsert() throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai";
String user="root";
String password="root"; //这里的密码要和你自己的对照
Connection connection = DriverManager.getConnection(url,user,password);
Statement statement = connection.createStatement();
String sql="insert into t_student values(null,'王五',16,'北京')";
statement.executeUpdate(sql);
}
@Test
public void testUpdate() throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai";
String user="root";
String password="root"; //这里的密码要和你自己的对照
Connection connection = DriverManager.getConnection(url,user,password);
Statement statement = connection.createStatement();
String sql="update t_student set name='闫克起',age=18,address='香港' where id=2";
statement.executeUpdate(sql);
}
}
四、查询功能 --- 查询数据库表中的记录
@Test //理解为main函数。可以独立运行。
public void testQuery() throws Exception { //抛出异常只是为了操作方便。真正在开发时应该try--catch
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection
("jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai", "root", "root");
Statement statement = conn.createStatement();
String sql = "select id,name,age,address from t_student";
//执行查询sql语句 并把数据库表中记录返回到ResultSet对象中进行保存。
ResultSet rs = statement.executeQuery(sql);
//取出ResultSet中表的记录。rs.next() 判断指针是否可以移动。如果可以移动则返回true,否则返回false
while (rs.next()) {
int id = rs.getInt("id"); //指针移动并获取指定列的值。
String name = rs.getString("name");
String address=rs.getString("address");
int age=rs.getInt("age");
System.out.println("id:"+id+";name:"+name+";age:"+age+";address:"+address);
}
}
4.1 根据条件查询
//根据条件查询数据库
@Test
public void testQueryByCondition() throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection
("jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai", "root", "root");
Statement statement = conn.createStatement();
String sql="select * from t_student where id=3";
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
int id = rs.getInt("id"); //指针移动并获取指定列的值。
String name = rs.getString("name");
String address=rs.getString("address");
int age=rs.getInt("age");
System.out.println("id:"+id+";name:"+name+";age:"+age+";address:"+address);
}
}
五、SQL注入问题
sql注入: sql中存在特殊字符时 则sql会按照特殊字符来解析。
演示sql注入的安全问题:
//演示sql注入的安全问题
public static void main(String [] args) throws Exception{
Scanner scanner=new Scanner(System.in); //Scanner类有没有讲过。
System.out.print("请输入账号:");
String username = scanner.nextLine();
System.out.print("请输入密码:");
String password = scanner.nextLine(); //你输入的账号和密码 nextLine() 可以输入空格 回车任认为结束 next()输入空格后认为输入结束。
boolean b = sqlSafe(username, password);
}
//根据name查询数据 abc 演示的根据账号和密码查询数据库表记录 如果能查询表示登录成功 否则登录失败
private static boolean sqlSafe(String name,String password) throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection
("jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai", "root", "root");
Statement statement = conn.createStatement();
//这里的admin 是不是一个死数据 123456 也是一个死数据
String sql="select * from t_user where username='"+name+"' and password='"+password+"'";
System.out.println(sql);
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("登录成功");
return true;
}
System.out.println("登录失败");
return false;
}
可以发现: 你的账号可以随便输入 你的密码也可以随便输入 但是 在输入密码时 or '4'='4 只要这个条件成立,那么你就能登录成功。 这个就是sql注入的安全问题。只要根据条件做sql。那么就会出现sql注入安全问题。
如何解决sql安全注入问题:
1. 前端做校验: --只防君子 防不了小人。
2. 后端也做校验:--难道以后每次写功能都进行校验吗? 代码变得复杂了。
3. 执行sql的类Statement出现了问题,后期PreparedStatement该类来解决sql注入安全问题。Statement和PreparedStatement区别?
Statement会出现sql注入安全问题。Preparedstatement不会出现sql注入安全问题。
Preparedstatement是Statement的子类。就是因为早期使用Statement发现该类出现问题,后期维护人员创建Statement的子类来解决这个问题。注意:维护人员不会再原类上做维护
六、使用PreparedStatement来解决sql注入的问题
因为Statement类导致了sql注入的危险!
如何解决:-----演变出一个Statement的子类----->PreparedStatement[重写相应的方法]
//演示sql注入的安全问题
public static void main(String [] args) throws Exception{
Scanner scanner=new Scanner(System.in); //Scanner类有没有讲过。
System.out.print("请输入账号:");
String username = scanner.nextLine();
System.out.print("请输入密码:");
String password = scanner.nextLine(); //你输入的账号和密码 nextLine() 可以输入空格 回车任认为结束 next()输入空格后认为输入结束。
boolean b = sqlSafe02(username, password);
}
private static boolean sqlSafe02(String name,String password) throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection
("jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai", "root", "root");
//使用PrepareStatement 这里的? 是占位符。
String sql="select * from t_user where username=? and password=?";
PreparedStatement ps = conn.prepareStatement(sql);//预编译sql
//为占位符赋值。根据占位符的类型使用不同的方法来赋值
ps.setString(1,name); //1表示第一个占位符 name:表示第一个占位符的值
ps.setString(2,password);
//执行sql语句
ResultSet rs = ps.executeQuery();
while (rs.next()){
System.out.println("登录成功");
return true;
}
System.out.println("登录失败");
return false;
}
6.1 使用PreparedStatement完成增删改查
@Test //增
public void insert() throws Exception{
//抛出异常只是为了操作方便。真正在开发时应该try--catch
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接对象
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/myaa?serverTimezone=Asia/Shanghai","root","123456");
//获取执行sql语句
String sql = "insert into t_user values(null,'王','123456')";
PreparedStatement ps = connection.prepareStatement(sql);//预编译
int i = ps.executeUpdate();//返回受影响的行数
System.out.println(i);
}
@Test //删
public void testDelete() throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai";
String user="root";
String pwd="root";
Connection connection = DriverManager.getConnection(url,user,pwd);
String sql="delete from t_student where id=?";
PreparedStatement ps = connection.prepareStatement(sql);
//为占位符赋值.
int id=5; //未来应该是传递过来的。
ps.setObject(1,id); //数据库中如果是其他类型 也可以使用''
//使用setObject
//执行sql语句 executeUpdate方法
ps.executeUpdate();
}
@Test //改
public void update() throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/myaa?serverTimezone=Asia/Shanghai","root","123456");
String sql = "update t_user set id=6,username='9568',password='147258' where id=?";
PreparedStatement ps = connection.prepareStatement(sql);//预编译
//为占位符赋值
int id = 3;
ps.setInt(1,id);
//执行sql语句
ps.executeUpdate();
}
@Test //查
public void select() throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/myaa?serverTimezone=Asia/Shanghai","root","123456");
String sql = "select * from t_user where id=?";
PreparedStatement ps = connection.prepareStatement(sql);//预编译
//为占位符赋值
int id = 2;
ps.setInt(1,id);
//执行sql语句 把数据库表中记录返回到ResultSet对象中
ResultSet rs = ps.executeQuery();
//取出ResultSet中的记录 rs.next()判断指针是否可以移动 如果可以返回true 否则返回false
while(rs.next()){
int id1 = rs.getInt("id");//移动指针并获取指定列的值
String username = rs.getString("username");
String password = rs.getString("password");
System.out.println(id1+"\t"+username+"\t"+password);
}
}