java学习笔记:PreparedStatement解决sql注入

java学习笔记:PreparedStatement解决sql注入

 

sql注入
----
sql注入:由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL 关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。

1_原因:
String sql = select * from user where username =' zhangsan' -- ' and password =' ' ;
例如:
恶意注入方式一:输入 username: 随意   password: ' or '1'='1 
select * from user where username ='xxxxx' and password ='xxx' or '1'='1'; 
* and 优先级 执行 高于 or 
恶意注入方式二、在SQL添加 -- 是mysql的注释 用户名框:输入 zhangsan' 空格--空格   password 随意
select * from user where username ='zhangsan' -- ' and password ='' ;
注意:以上的 zhangsan' 空格--空格 中的zhangsan是数据库存在的
 

 

解决sql注入
----
1.PreparedStatement解决sql注入,重要步骤:
PreparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatement(sql)方法获得。
Connection::PreparedStatement prepareStatement(String sql);//Creates a PreparedStatement object for sending parameterized SQL statements to the database. 
注意:sql是提前创建好的,sql语句中需要参数,使用?进行占位。
举例:
select * from user where username='zhangsan' and password='123456';
使用?进行占位
select * from user where username=? and password=?;
步骤一:conn.prepareStatement(sql);//需要你事先传递sql。如果sql需要参数,使用?进行占位。
步骤二:设置参数(执行sql之前):prepStmt.setXXX(int index, 要放入的值);//根据不同类型的数据进行方法的选择。第一个参数表示的是?出现的位置,从1开始计数,有几个问号,就需要传递几个参数。
方法的参数说明:
第一个参数:int index:表示的是问号出现的位置,问号是从1开始计数。
第二个参数:要问号的位置传入的值
步骤三:执行,不需要再传递sql了
prepStmt.executeQuery();//执行select
prepStmt.executeUpdate();//执行insert, delete, update等

2.代码
@Test
    public void select(){
        //需求:根据用户名和密码查询
        Connection conn = null;
        PreparedStatement preStmt = null;
        ResultSet rs = null;

        try{
            //获得连接
            conn = JDBCUtils.getConnection();
            //获得发送sql的对象
            String sql = "select * from user where username=? and password=?;";
            preStmt = conn.prepareStatement(sql);
            //设置参数
            preStmt.setString(1, "lisi");
            preStmt.setString(2, "123");
            //发送sql获得结果
            rs = preStmt.executeQuery();
            //处理结果
            if(rs.next()){
                int id = rs.getInt("id");
                String username = rs.getString("username");
                String password = rs.getString("password");
                System.out.println(id + "::" + username + "::" + password);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        finally{
            JDBCUtils.release(conn, preStmt, rs);
        }
    }//end of method select

    @Test
    public void insert(){
        //需求:添加用户 名为杨颖
        Connection conn = null;
        PreparedStatement preStmt = null;

        try{
            //获得连接
            conn = JDBCUtils.getConnection();
            //获得发送sql的对象
            String sql = "insert into user values(null, ?, ?);";
            preStmt = conn.prepareStatement(sql);
            //设置参数
            preStmt.setString(1, "杨颖");
            preStmt.setString(2, "123456");
            //发送sql获得结果
            int sum = preStmt.executeUpdate();
            //处理结果
            System.out.println(sum);
        }catch(Exception e){e.printStackTrace();}finally{JDBCUtils.release(conn, preStmt);}
    }//end of method insert

3.PreparedStatement解决SQL注入原理:
运行在sql中参数以?占位符的方式表示
select * from user where username=? and password=?;
将带有?的sql发送给数据库完成编译(不能执行的sql带有?的sql进行编译叫做预编译),在sql编译后发现缺少两个参数。PreparedStatement可以将?代替参数发送给数据库服务器,因为sql已经编译过,参数中特殊字符不会当做特殊字符编译,无法达到sql注入的目的。
 

你可能感兴趣的:(Java)