JDBC登录实践和SQL注入解决方法

登录实践操作

/*
1.会出现SQL注入操作
2.测试结果
	用户名:fff
	密码:fff' or '1'='1
	登录成功
*/
public class JDBCTest01{
    public static void main(String[] args){
        //初始化一个界面
        Map<String,String> userLoginInfo = initUI();
        //验证用户名和密码
        boolean loginSuccess = login(userLoginInfo);
        //最后输出结果
        System.out.println(loginSuccess ? "登陆成功" : "登录失败");
    }
    /*
    用户登录
    userLoginInfo 用户登录信息
    return false表示失败   true表示成功
    */    
    pricate static boolean login(Map<String,String> userLoginInfo){
        //打标记的意识
        boolean loginSuccess = false;
        //单独定义变量
        String loginName = userLoginInfo.get("loginName");
        String loginPwd = userLoginInfo.get("loginPwd");
        //JDBC代码
        Connection conn = null;
        Statement stmt = null;//使用PreparedStatement(预编译的数据库操作对象)
        ResultSet re = null;
        try{
            //1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");        		//2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
            //3.获取与编译的数据库操作对象
            stmt = conn.createStatement();
            //4.执行SQL
            String sql = "select * from t_user where loginName = '"+loginName+"' and loginPwd = '"+loginPwd+"' ";
            re = stmt.executeQuery(sql);
            //5.处理结果集
            if(re.next()){
                //登录成功
                loginSuccess = true;
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            //6.释放资源
            if(re!=null){
                try{
                    re.close();
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
            if(stmt!=null){
                try{
                    stmt.close();
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try{
                    conn.close();
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
    private static Map<String,String> initUi(){
        Scanner s = new Scanner(System.in);
        System.out.print("用户名:");
        String loginName = s.nextLine();
        System.out.print("密码:");
        String loginPwd = s.nextLine();
        Map<String,String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("loginName",loginName);
        userLoginInfo.put("loginPwd",loginPwd);
        return userLoginInfo;
    }
}

SQL注入解决方法

/*
1.解决SQL注入问题
	只要用户提供的信息不参与SQL语句的编译过程,问题就解决了
	即使用户提供的信息中含有SQL语句的关键字,但是没有参与编译
	要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
	PreparedStatement接口继承了java.sql.Statement
	PreparedStatement是属于预编译的数据库操作对象
	PreparedStatement的原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传"值"
2.测试结果
	用户名:fff
	密码:fff' or '1'='1
	登录失败
3.解决SQL注入的关键是:
	用户提供的信息中即使含有SQL语句的关键字,但是这些关键字并没有参与编译,不起作用
4.PreparedStatement和Statement区别
	Statement存在SQL注入问题,PreparedStatement解决了SQL注入问题
	Statement是编译一次执行一次,PreparedStatement是编译一次,可执行N次,PreparedStatement效率较高一些
	PreparedStatement会在编译阶段做类型的安全检查
5.什么情况下必须使用Statement?
	业务方面要求必须支持SQL注入的时候
	Statement支持SQL注入,凡是业务方面要求是需要进行SQL语句拼接的,必须使用Statement
*/
public class JDBCTest01{
    public static void main(String[] args){
        //初始化一个界面
        Map<String,String> userLoginInfo = initUI();
        //验证用户名和密码
        boolean loginSuccess = login(userLoginInfo);
        //最后输出结果
        System.out.println(loginSuccess ? "登陆成功" : "登录失败");
    }
    /*
    用户登录
    userLoginInfo 用户登录信息
    return false表示失败   true表示成功
    */    
    pricate static boolean login(Map<String,String> userLoginInfo){
        //打标记的意识
        boolean loginSuccess = false;
        //单独定义变量
        String loginName = userLoginInfo.get("loginName");
        String loginPwd = userLoginInfo.get("loginPwd");
        //JDBC代码
        Connection conn = null;
        PreparedStatement ps = null;//使用PreparedStatement(预编译的数据库操作对象)
        ResultSet re = null;
        try{
            //1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");        		//2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
            //3.获取与编译的数据库操作对象
            //SQL语句的框子 其中一个 ? 代表一个占位符,一个 ? 将来接收一个"值",注意:占位符不能使用单引号括起来
            String sql = "select * from t_user where loginName = ? and loginPwd = ? ";
            //程序执行到此处,会发送SQL语句框子给DBMS,然后DBMS进行SQL语句的预先编译
            ps = conn.prepareStatement(sql);
            //给占位符 ? 传值(第一个问号下标为1,第二个问号下标为2,JDBC中所有下标从1开始)
            ps.setString(1,loginName);
            ps.setString(2,loginPwd);
            //4.执行SQL
            re = ps.escuteQuery()//SQL语句已经预先编译,不需要再插入SQL语句
            //5.处理结果集
            if(re.next()){
                //登录成功
                loginSuccess = true;
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            //6.释放资源
            if(re!=null){
                try{
                    re.close();
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
            if(ps!=null){
                try{
                    ps.close();
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try{
                    conn.close();
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
    private static Map<String,String> initUi(){
        Scanner s = new Scanner(System.in);
        System.out.print("用户名:");
        String loginName = s.nextLine();
        System.out.print("密码:");
        String loginPwd = s.nextLine();
        Map<String,String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("loginName",loginName);
        userLoginInfo.put("loginPwd",loginPwd);
        return userLoginInfo;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值