• java学习day24-JDBC-PreparedStatment预编译对象


    PreparedStatement预编译对象

    PreparedStatement

    在开发中我们用的更多的传输器对象是PreparedStatement对象,PreparedStatement是Statement的子接口,比Statement更加安全,并且能够提高程序执行的效率。

    Statement 父对象

    PreparedStatement 子对象

    模拟用户登录案例

    (1)准备数据

    use jt_db;
    create table user(
        id int primary key auto_increment,
        username varchar(50),
        password varchar(50)
    );
    insert into user values(null,'张三','123');
    insert into user values(null,'李四','234');
    

    (2)创建LoginUser 类,提供 main 方法 和 login 方法。

    public static void main(String[] args) {
    	/* 1、提示用户登录,提示用户输入用户名并接收用户名
    	 *  2、提示用户输入密码并接收密码
    	 *  3、根据用户名和密码查询用户信息
    	 */
    	// 1、提示用户登录,提示用户输入用户名并接收用户名
    	Scanner sc = new Scanner(System.in);
    	System.out.println( "请登录:" );
    	System.out.println( "请输入用户名:" );
    	String user = sc.nextLine();
    	
    	// 2、提示用户输入密码并接收密码
    	System.out.println( "请输入密码:" );
    	String pwd = sc.nextLine();
    	
    	// 3、根据用户名和密码查询用户信息
    	login( user, pwd );
    }
    /**
     * 根据用户名和密码查询用户信息
     * @param user 用户名
     * @param pwd 密码
     */
    private static void login(String user, String pwd) {
    	Connection conn = null;
    	Statement stat = null;
    	ResultSet rs = null;
    	try {
    		//1.注册驱动并获取连接
    		conn = JdbcUtil.getConn();
    		//2.获取传输器,执行sql并返回执行结果
    		stat = conn.createStatement();
    		String sql = "select * from user where username='"+user+"' and password='"+pwd+"'";
    		rs = stat.executeQuery(sql);
    		System.out.println( sql );
    		//3.处理结果
    		if( rs.next() ) { //有数据 -- 用户名密码都正确
    			System.out.println("恭喜您登录成功!");
    		}else { //没数据 -- 用户名或密码不正确
    			System.out.println("登录失败, 用户名或密码不正确!");
    		}
    	} catch (Exception e) {
    		e.printStackTrace();
    	} finally {
    		//4.释放资源
    		JdbcUtil.close(conn, stat, rs);
    	}
    }
    

    执行时,输入:

    请登录:
    请输入用户名:
    张飞'#'
    请输入密码:
    
    select * from user where username='张飞'#'' and password=''
    恭喜您登录成功了!
    

    或输入

    请登录:
    请输入用户名:
    张飞' or '1=1
    请输入密码:
    
    select * from user where username='张飞' or '1=1' and password=''
    恭喜您登录成功了!
    

    或输入

    请登录:
    请输入用户名:
    
    请输入密码:
    ' or '2=2
    select * from user where username='' and password='' or '2=2'
    恭喜您登录成功了!
    

    SQL注入攻击

    通过上面的案例,我们发现在执行时,不输入密码只输入用户名也可以登陆成功。这就是SQL注入攻击。

    SQL注入攻击产生的原因: 由于后台执行的SQL语句是拼接而来的

    select * from user where username='"+user+"' and password='"+pwd+"'
    

    其中的参数是用户提交过来的,如果用户在提交参数时,在参数中掺杂了一些SQL关键字(比如or)或者特殊符号(#、-- 、' 等),就可能会导致SQL语句语义的变化,从而执行一些意外的操作(用户名或密码不正确也能登录成功)!

    防止SQL注入攻击

    如何防止SQL注入攻击?

    (1)使用正则表达式对用户提交的参数进行校验。如果参数中有(# -- ' or等)这些符号就直接结束程序,通知用户输入的参数不合法

    (2)使用PreparedStatement对象来替代Statement对象。

    下面通过第二种方式解决SQL注入攻击:添加loginByPreparedSatement方法,在方法中,使用PreparedStatement来代替Statement作为传输器对象使用,代码示例:

    /**
     * 根据用户名和密码查询用户信息
     * @param user 用户名
     * @param pwd 密码
     */
    private static void login(String user, String pwd) {
    	Connection conn = null;
    	PreparedStatement ps = null;
    	ResultSet rs = null;
    	try {
    		//1.注册驱动并获取连接
    		conn = JdbcUtil.getConn();
    		//2.获取传输器,执行sql并返回执行结果
    		String sql = "select * from user where username=? and password=?";
    		ps = conn.prepareStatement( sql );
    		//设置SQL语句中的参数
    		ps.setString( 1 , user );
    		ps.setString( 2 , pwd );
    		//执行SQL语句
    		rs = ps.executeQuery();//这里不要再传输SQL语句
    		
    		//3.处理结果
    		if( rs.next() ) { //有数据 -- 用户名密码都正确
    			System.out.println("恭喜您登录成功!");
    		}else { //没数据 -- 用户名或密码不正确
    			System.out.println("登录失败, 用户名或密码不正确!");
    		}
    	} catch (Exception e) {
    		e.printStackTrace();
    	} finally {
    		//4.释放资源
    		JdbcUtil.close(conn, ps, rs);
    	}
    }
    

    再次执行程序,按照上面的操作登录。此时,已经成功的防止了SQL注入攻击问题了。

    PreparedStatement对象是如何防止SQL注入攻击的:

    使用PreparedStatement对象是先将SQL语句的骨架发送给服务器编译并确定下来,编译之后SQL语句的骨架和语义就不会再被改变了,再将SQL语句中的参数发送给服务器,即使参数中再包含SQL关键字或者特殊符号,也不会导致SQL语句的骨架或语义被改变,只会被当作普通的文本来处理!


    使用PreparedStatement对象的好处:

    可以防止SQL注入攻击

    而且通过方法设置参数更加的方便且不易出错!

    还可以从某些方面提高程序执行的效率!

  • 相关阅读:
    Windows之shortcut
    VHDL之code structure
    Embedded之Makefile
    VHDL_LIB之DFF
    VCS之Git
    潭州课堂25班:Ph201805201 django框架 第五课 自定义简单标签,包含标签,模型类创建,梳理类创建 (课堂笔记)
    潭州课堂25班:Ph201805201 django框架 第四课 模板常用标签,模板继承与引用,自定义过渡器 (课堂笔记)
    潭州课堂25班:Ph201805201 django框架 第三课 模板路径,变量,过滤器,静态文件的引用 (课堂笔记)
    潭州课堂25班:Ph201805201 django框架 第二课 url,,include,kwargs,name的使用 (课堂笔记)
    潭州课堂25班:Ph201805201 django框架 第一课 环境搭建 (课堂笔记)
  • 原文地址:https://www.cnblogs.com/liqbk/p/13033164.html
Copyright © 2020-2023  润新知