【JDBC】学习路径3-密码登录&SQL注入攻击

Posted on 2022-05-23 11:16  罗芭Remoo  阅读(79)  评论(0)    收藏  举报

最后再提醒一句,每次在测试JDBC程序的时候,一定要确保MySQL正在运行。

打开控制台(终端),输入mysql

如果没启动,则出现以下提示:

Mac端启动MySQL数据库,需要在系统便好设置中启动。


第一章:构建登录校验客户端

测试数据库:

当用户输入了正确的账号密码时,这个函数返回true,反之。

查看代码
public static boolean selectWithUsernamePassword(String username,String password){
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/jdbc_01?useUnicode=true&characterEncoding=UTF8";

            con = DriverManager.getConnection(url,"root","88888888");

            stmt = con.createStatement();

            String sql = "select * from user where username ='"+username+"'and password ='"+password+"'";
            System.out.println(sql);
            rs = stmt.executeQuery(sql);

            if(rs.next())
                return true;
            else
                return false;

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (stmt != null)
                    stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (con != null)
                    con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return false;
    }

 

 

其中,这一行时我们组拼的SQL语句:

String sql = "select * from user where username ='"+username+"'and password ='"+password+"'";

 

 

我们在main方法中调用测试一下:

selectWithUsernamePassword("remoo1","1234");

返回的是true;

若输入了数据库中不存在的数据,则返回false。


第二章:SQL注入攻击

当我们密码输入为:

selectWithUsernamePassword("nijsfies","1sadf' or '1'='1");

时,我们发现,无论你密码是否正确,最后都会输出true。

 

 我们组拼的完整的SQL语句如下:

select * from user where username ='nijsfies'and password ='1234' or '1'='1'

相当于:select * from user where (username ='asd' and password = 'asd') or '1'='1'

 

where后面有两个条件:用户名密码满足xxx、‘1’=‘1’

显然‘1’=‘1’(SQL语句中等号为=,而不是==),

后面的每一条数据都满足1=1这个条件,

所以一定返回全部数据。

第三章:阻止SQL注入

如何解决?使用PreparedStatement()

查看代码

public static boolean safe_SelectWithUP(String username,String password){
        Connection con = null;
        //Statement stmt = null;
        ResultSet rs = null;
        PreparedStatement pstmt = null;
        try {
            //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/jdbc_01?useUnicode=true&characterEncoding=UTF8";

            con = DriverManager.getConnection(url,"root","88888888");

//            stmt = con.createStatement();
//            String sql = "select * from user where username ='"+username+"'and password ='"+password+"'";
//            System.out.println(sql);
//            rs = stmt.executeQuery(sql);

            //?代表一个参数
            String sql = "select * from user where username = ? and password = ?";

            pstmt = con.prepareStatement(sql);
            pstmt.setString(1,username);
            pstmt.setString(2,password);

            //上面已经传递了SQl语句了,这里直接执行就好了。
            //SQL语句已经存储在pstmt内部了,并且对SQL注入攻击进行了防范。
            rs = pstmt.executeQuery();
            System.out.println(sql);


            if(rs.next())
                return true;
            else
                return false;

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (pstmt != null)
                    pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (con != null)
                    con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return false;
    }

 测试结果: