感谢传智播客提供的学习视频 ,希望传智播客越来越好

l  它是Statement接口的子接口;

l  强大之处:

Ø  防SQL攻击;

Ø  提高代码的可读性、可维护性;

Ø  提高效率!

l  学习PreparedStatement的用法:

Ø  如何得到PreparedStatement对象:

¨      给出SQL模板!

¨      调用Connection的PreparedStatement prepareStatement(String sql模板);

¨      调用pstmt的setXxx()系列方法sql模板中的?赋值!

¨      调用pstmt的executeUpdate()或executeQuery(),但它的方法都没有参数。

l  预处理的原理

Ø  服务器的工作:

¨      校验sql语句的语法!

¨      编译:一个与函数相似的东西!

¨      执行:调用函数

Ø  PreparedStatement:

¨      前提:连接的数据库必须支持预处理!几乎没有不支持的!

¨      每个pstmt都与一个sql模板绑定在一起,先把sql模板给数据库,数据库先进行校验,再进行编译。执行时只是把参数传递过去而已!

¨      若二次执行时,就不用再次校验语法,也不用再次编译!直接执行!

1 什么是SQL攻击

在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的SQL语句合成一个完整的SQL语句!例如用户在登录时输入的用户名和密码都是为SQL语句的片段!

2 演示SQL攻击

首先我们需要创建一张用户表,用来存储用户的信息。

CREATE TABLE user(

         uid   CHAR(32) PRIMARY KEY,

         username        VARCHAR(30) UNIQUE KEY NOT NULL,

         PASSWORD    VARCHAR(30)

);

 

INSERT INTO user VALUES('U_1001', 'zs', 'zs');

SELECT * FROM user;

现在用户表中只有一行记录,就是zs。

下面我们写一个login()方法!

public void login(String username, String password) {

Connection con = null;

Statement stmt = null;

ResultSet rs = null;

try {

con = JdbcUtils.getConnection();

stmt = con.createStatement();

String sql = "SELECT * FROM user WHERE " +

"username='" + username +

"' and password='" + password +"'";

rs = stmt.executeQuery(sql);

if(rs.next()) {

System.out.println("欢迎" + rs.getString("username"));

} else {

System.out.println("用户名或密码错误!");

}

} catch (Exception e) {

throw new RuntimeException(e);

} finally {

JdbcUtils.close(con, stmt, rs);

}

}

下面是调用这个方法的代码:

login("a' or 'a'='a", "a' or 'a'='a");

这行当前会使我们登录成功!因为是输入的用户名和密码是SQL语句片段,最终与我们的login()方法中的SQL语句组合在一起!我们来看看组合在一起的SQL语句:

SELECT * FROM tab_user WHERE username='a' or 'a'='a' and password='a' or 'a'='a'

3 防止SQL攻击

l  过滤用户输入的数据中是否包含非法字符;

l  分步交验!先使用用户名来查询用户,如果查找到了,再比较密码;

l  使用PreparedStatement。

4 PreparedStatement是什么?

PreparedStatement叫预编译声明!

PreparedStatement是Statement的子接口,你可以使用PreparedStatement来替换Statement。

PreparedStatement的好处:

l  防止SQL攻击;[c1]

l  提高代码的可读性,以可维护性;

l  提高效率[c2] 。

5 PreparedStatement的使用

l  使用Connection的prepareStatement(Stringsql):即创建它时就让它与一条SQL模板绑定;

l  调用PreparedStatement的setXXX()系列方法为问号设置值

l  调用executeUpdate()或executeQuery()方法,但要注意,调用没有参数的方法;

String sql = “select * from tab_student where s_number=?”;

PreparedStatement pstmt = con.prepareStatement(sql);

pstmt.setString(1, “S_1001”);

ResultSet rs = pstmt.executeQuery();

rs.close();

pstmt.clearParameters();[崔3]

pstmt.setString(1, “S_1002”);

rs = pstmt.executeQuery();

在使用Connection创建PreparedStatement对象时需要给出一个SQL模板,所谓SQL模板就是有“?”的SQL语句,其中“?”就是参数。

在得到PreparedStatement对象后,调用它的setXXX()方法为“?”赋值,这样就可以得到把模板变成一条完整的SQL语句,然后再调用PreparedStatement对象的executeQuery()方法获取ResultSet对象。

注意PreparedStatement对象独有的executeQuery()方法是没有参数的,而Statement的executeQuery()是需要参数(SQL语句)的。因为在创建PreparedStatement对象时已经让它与一条SQL模板绑定在一起了,所以在调用它的executeQuery()和executeUpdate()方法时就不再需要参数了。

PreparedStatement最大的好处就是在于重复使用同一模板,给予其不同的参数来重复的使用它。这才是真正提高效率的原因。

所以,建议大家在今后的开发中,无论什么情况,都去需要PreparedStatement,而不是使用Statement。


[c1]不只它可以防!

[c2]很重要!

[崔3]再次使用时需要把原来的设置清空。

<pre name="code" class="java">package cn.itcast.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;import org.junit.Test;import com.mysql.jdbc.PreparedStatement;public class JdbcPreparedStatement {/*** 登录方法  可以被SQL攻击的* 使用UserName和UserCode去查询数据库* @throws ClassNotFoundException * @throws SQLException */public boolean loginOne(String username,String password) throws Exception{/*** 一、得到Connection* 二、得到Statement* 三、得到ResultSet* 四、rs.next()返回的是什么,我们就返回什么*///准备四大参数String driverClassName="com.mysql.jdbc.Driver";String url="jdbc:mysql://localhost:3306/db3";String myUserName="root";String mypassword="123";//加载驱动类Class.forName(driverClassName);//得到connectionConnection con=DriverManager.getConnection(url,myUserName,mypassword);//得到statementStatement statm=con.createStatement();//给出SQL语句String sql="select * from student where UserName='"+username+"' and UserCode='"+password+"'";//在这可以输出SQL,是否写正确//System.out.println(sql);//执行SQL语句,调用statm中的excuteQuery(),得到ResultSetResultSet rs=statm.executeQuery(sql);//设置返回值 ,有结果表示查询到数据,没有,表示没有查询到return rs.next();}@Testpublic void fun1() throws Exception {String userName="a'or 'a'='a";String passWord="a'or 'a'='a";//这样传过去的SQL结果是:这就是SQL注入攻击//select * from student where UserName='a'or 'a'='a' and UserCode='a'or 'a'='a'boolean bool= loginOne(userName,passWord);System.out.println(bool); }/*** 防SQL攻击的登录* @throws Exception*/public boolean loginTwo(String username,String password) throws Exception{/*** 一、得到Connection* 二、得到Statement* 三、得到ResultSet* 四、rs.next()返回的是什么,我们就返回什么*///准备四大参数String driverClassName="com.mysql.jdbc.Driver";String url="jdbc:mysql://localhost:3306/db3";String myUserName="root";String mypassword="123";//加载驱动类Class.forName(driverClassName);//得到connectionConnection con=DriverManager.getConnection(url,myUserName,mypassword);///从这里开始,与上面的loginOne()方法中不一样,这里使用的是preparedStatement对象来处理 /** 得到preparedStatement*  1,给出SQL模板:所有的参数使用?来替代
//       *  2.调用connection的preparedStatement()方法来生成preparedStatement对象*  3,给SQL模板赋值 ,用preStatm.setString方法来赋值 *  4,调用 preparedStatement的executeQuery方法,来执行语句*///给出SQL模板String sqlTwo="select * from student where UserName=? and UserCode=?";//得到 preparedStatement对象PreparedStatement preStatm =  (PreparedStatement) con.prepareStatement(sqlTwo);//给参数赋值 preStatm.setString(1, username);preStatm.setString(2, password);//调用 preStatm的executeQuery方法,来执行语句ResultSet rsTwo= preStatm.executeQuery();//没有参数的,向数据库发送查询方法//得到查询结果return rsTwo.next();}@Testpublic void TestTwo() throws Exception {String userName="ZhangSan";String PassWord="201401";boolean bool=loginTwo(userName, PassWord);System.out.println(bool);}
}

PreparedStatement JDBC域处理/SQl攻击相关推荐

  1. jdbc(跟着宝哥学java:jdbc) jdbc概念,铁打步骤,jdbc封装,预编译对象,sql攻击

    1 概念 jdbc:java database connection 通过java连接数据库 sun公司为java连接所有数据库提供的一组接口; jdbc驱动:各个数据库厂家为自己的数据库根据jdbc ...

  2. jdbc之防sql注入攻击

    1.SQL注入攻击:     由于dao中执行的SQL语句是拼接出来的,其中有一部分内容是由用户从客户端传入,所以当用户传入的数据中包含sql关键字时,就有可能通过这些关键字改变sql语句的语义,从而 ...

  3. 2020-08-02 Mysql数据库索引初识、备份、设计原则、JDBC连接、SQL注入、PreparedStatement对象使用、事务处理、连接池

    ------------------------索引---------------------- 定义:帮助MYSQL高效获取数据的数据结构 ----------主键索引----------prima ...

  4. JDBC如何有效防止SQL注入

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53769810 本文出自[DylanAndroid的博客] JDBC如何有效防止 ...

  5. JDBC如何防止SQL注入

    JDBC如何有效防止SQL注入 在我们平时的开发中,作为新手写JDBC很有可能忽略了一点,那就是根本没有考虑SQL注入的问题, 那么,什么是SQL注入,以及如何防止SQL注入的问题. 1.什么是SQL ...

  6. JDBC中的SQL注入

    1.JDBC中sql注入 1.1 JDBC JDBC的概念:JDBC是sun公司(已被Oracle收购)制定一系列接口标准,由不同数据库厂商(Oracle.MySQL等)实现接口方法并封装成驱动文件, ...

  7. 【转】从源码分析PreparedStatement是如何防止SQL注入的?

    为什么在Java中PreparedStatement能够有效防止SQL注入?这可能是每个Java程序员思考过的问题. 首先我们来看下直观的现象(注:需要提前打开mysql的SQL文日志) 1. 不使用 ...

  8. PreparedStatement是如何防止SQL注入的?

    为什么在Java中PreparedStatement能够有效防止SQL注入?这可能是每个Java程序员思考过的问题. 首先我们来看下直观的现象(注:需要提前打开mysql的SQL文日志) 1. 不使用 ...

  9. JAVA使用JDBC批量插入SQL

    数据库连接使用proxool连接JDBC 代码 JAVA类 package com.czr.proxool;import org.logicalcobwebs.proxool.ProxoolExcep ...

最新文章

  1. CentOS 安装Python3
  2. Linux 中创建 USB 启动盘来拯救 Windows 用户
  3. 亿级流量架构之服务器扩容思路及问题分析
  4. 最常用的6种原型文件格式对比
  5. Tomcat 使用apr优化
  6. 4.6.2 定义内表
  7. Django Rest framework的限流实现流程
  8. while 循环的理解
  9. [转]Linux芯片级移植与底层驱动(基于3.7.4内核)
  10. linux tracker服务器搭建,linux 下 BT Tracker服务器搭建
  11. Linux shell:echo N > /proc/sys/vm/drop_caches清理缓存
  12. android 代码 混淆- 原来如此简单
  13. 施一公:如何成为一名优秀的博士生?
  14. 计算机工程制图箭头怎么画,cad中箭头画法
  15. 详谈!抖音蓝V认证的常见问题总结
  16. Chapter9.2:线性系统的状态空间分析与综合(上)
  17. python对文件的写作方法_python读写csv文件 - 作文写作问答 - 归教作文网
  18. 正则(数字或者以英文逗号隔开的数字字符串)
  19. flappybird android源码,iOS学习之flappyBird游戏的实现
  20. Creo 9.0安装教程

热门文章

  1. 可折叠手机Galaxy Fold被曝屏幕问题后 三星股价下跌逾3%
  2. 特朗普回应“蒂姆·苹果”事件:就是为节省时间
  3. 一加7海外提前上架 骁龙855+12GB超大内存
  4. 春节档总票房突破50亿元 《流浪地球》独占16亿!
  5. 为什么面试总喜欢考算法题?
  6. 人生苦短,喝点python性能鸡汤
  7. mysql5.6 load_MySQL 5.6 dump/load buffer pool实验
  8. GLSurfaceView源码分析以及简单使用
  9. 获取本机IP和MAC地址
  10. 我的YUV播放器MFC小笔记:非模态对话框建立及窗口间传值