浅析Statement类SQL注入问题

浅析Statement类SQL注入问题

       Statement接口是java.sql包下的一个接口,是官方提供的用来操作数据库的标准接口之一。接口的实现一般在数据库驱动中。因为所有的与数据库之间的交互都是基于连接对象的,所以它也是由连接对象获取返回的。返回的Statement类对象可以理解为是Java执行SQL语句的对象。

简单使用(以MySQL数据库为例)

//获得连接
Connection connection = DriverManager.getConnection(url, user, password);
//创建执行sql语句对象
Statement statement = connection.createStatement();
//执行sql,处理结果
String sql = “select * from user”;
//返回结果集对象
ResultSet resultSet = statement.executeQuery(sql);

SQL注入问题

       什么是SQL注入问题?我们在编写SQL语句的时候不可能是所有的条件都确定的。比如说用户登录的时候,账户和密码都是手动在用户层传入进来,而处在数据访问层的数据库交互代码是无法提前预知其信息的。因此。在编写SQL语句实现某个功能的时候,就不得不采用参数变量占位的方式来处理。
以下方简单的一个登录功能为例

private static void login(String username, String password) {
Connection con=null;
Statement st=null;
ResultSet rs=null;
try {
       con = Work2.getConnection();
       st = con.createStatement();
       //由数据库确认用户表中是否有对应的用户名且密码正确
       String sql=“SELECT * FROM USER1        where NAME =’”+username+"’ AND        password=’"+password+"’ ";
       rs = st.executeQuery(sql);
        if (rs.next()){
               System.out.println(“登录成功”);
       }else {
               System.out.println(“登录失败”);
        }
}catch (Exception e){
        e.printStackTrace();
}finally {
        Work2.close(con,st,rs);
}
(Work2是临时简单编写的JDBC工具类,仅为演示时减少代码量使用)

       在一些刚刚接触Java的朋友看来,这样不是很OK吗?通过传入的变量名可以准确传输用户的信息,再与写好的SQL语句结合到一起,不就是组成了一条完整且是我们需要的SQL语句了吗?这就要谈到SQL注入问题了
       SQL注入问题是指把用户输入的内容注入到了SQL语句里面去了, 比如说把用户输入or等字符当成sql的关键字了,把用户输入#当成关键字,将后面的内容给注释掉了等等。不仅妨碍了用户使用,更大的问题是存在安全隐患。比如说SELECT * FROM user1 WHERE username = ‘zs’ AND password =’’ or ‘’=’’ 这样的只需要用户名正确的语句,以及SELECT * FROM user WHERE username = ‘zs’ AND password =’’ or true 这样的连用户名都可以不需要正确的语句。因此,这也是后来推出预编译对象PrepareStatement的原因之一

问题的解决

       PrepareStatement接口是Statement的子接口之一,同样是官方推出的标准接口,由驱动厂商实现。由连接对象返回的PrepareStatement类是Statement的子类。其特点是可以做SQL的批处理并且可以解决SQL注入问题
       那如何使用呢?将SQL语句中的变量都用 ? 作为占位符代替,之后通过setXXX方法为?赋值,再调用executeUpdate或executeQuery方法执行SQL语句即可

//定义SQL语句
String sql1=“update user set nickname=? where username=admin”;
//执行SQL语句
ps = con.prepareStatement(sql1);
//给占位符赋值
ps.setString(1,nickname);//第一个参数是表示第几个?,第二个则是值
//处理执行结果
int i = ps.executeUpdate();
System.out.println(i);
       Setxxx方法需要传入两个参数,第一个是表示这句代码是给上面SQL语句中的第几个?,第二个是给SQL语句的那个变量赋值。setXXX的XXX表示这个部分赋值的数据类型,比如说setString(1,”XXX”)

你可能感兴趣的:(JDBC)