本程序是模拟用户登录 并且解决SQL注入问题 sql注入的根本原因是:先进行字符串的拼接,再进行编译 程序说明:本程序的输入采取了scanner.nextline()方法 即意味着可以接收一行的密码 而密码是sql语言的一部分,因此可以创建 or 关键字破坏sql的where条件 例如:
此时人为地破坏了sql正常的语句。
原本的代码:
//3.获取数据库 *** 作对象 stmt = conn.createStatement(); //4.执行sql语句 // mysql语句有单引号如何写入String // 1.首先按照sql语句写下你要查询的语句,变量的地方先空着 // 2.然后在单引号里加双引号和两个加号 如 '"++"' 此时再向两个加号之间加上变量。 // String sql = "select * from t_user where login_name ='' and login_pwd=''"; String sql = "select * from t_user where login_name ='"+loginname+"' and login_pwd='"+loginpwd+"'"; // 3.但是这种情况会出现sql的注入问题(即输入的密码为 123 or '1'= 1 ) rs = stmt.executeQuery(sql);//rs返回的是光标
解决方法为:改变原本的Statement *** 作对象,使用预编译的 *** 作对象PreparedStatement
package JDBC; import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.ResourceBundle; import java.util.Scanner; public class JDBClogin_user { public static void main(String[] args) { // 自动创建函数:只需要在未创建的函数名处使用alt+enter 即可为其创建函数 //初始化界面 Mapuserlogin_info = initUI(); //链接数据库,验证用户名和密码是否正确 boolean ok = check_nameandpwd(userlogin_info.get("loginname"),userlogin_info.get("loginpwd")); System.out.println(ok ? "登录成功" : "登录失败");// ?为正,登录成功,否则登录失败 } private static boolean check_nameandpwd(String loginname, String loginpwd) { //数据库的六部 哐哐哐打出来或者找之前写好的模板直接复制 这里采取第二种注册驱动的方法 Connection conn = null; // Statement stmt = null; PreparedStatement stmt = null; ResultSet rs = null; //资源绑定器 ResourceBundle bundle = ResourceBundle.getBundle("resourses/db"); String driver= bundle.getString("driver"); String url = bundle.getString("url"); String user = bundle.getString("user"); String password = bundle.getString("password"); //下面的模板就是 try{...}catch{...}finally{...} try{ //1.注册驱动的第二种方式:类加载注册 // Class.forName("com.mysql.jdbc.Driver");//可以写到配置文件当中 Class.forName(driver); //2.获取连接 // conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/trade_for_book","root","002415"); conn = DriverManager.getConnection(url,user,password); //3.获取数据库 *** 作对象 // stmt = conn.createStatement(); String sql = "select * from t_user where login_name = ? and login_pwd= ?";//一个问号是一个占位符,只能接受一个值 stmt = conn.prepareStatement(sql); //给问号传值 那么无论你输入的有什么关键字,最终只是一个值,不会改变sql语句的条件 stmt.setString(1,loginname); stmt.setString(2,loginpwd); //4.执行sql语句 // mysql语句有单引号如何写入String // 1.首先按照sql语句写下你要查询的语句,变量的地方先空着 // 2.然后在单引号里加双引号和两个加号 如 '"++"' 此时再向两个加号之间加上变量。 // String sql = "select * from t_user where login_name ='' and login_pwd=''"; // String sql = "select * from t_user where login_name ='"+loginname+"' and login_pwd='"+loginpwd+"'"; // 3.但是这种情况会出现sql的注入问题(即输入的密码为 123 or '1'= 1 ) // rs = stmt.executeQuery(sql);//rs返回的是光标 rs = stmt.executeQuery();//预编译就不需要传sql语句了 // System.out.println(sql); if (rs.next()){ return true; }else { return false; } }catch(Exception e){ e.printStackTrace(); }finally { if (rs != null){ try{ rs.close(); }catch(SQLException e){ e.printStackTrace(); } } if (stmt != null){ try{ stmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if (conn != null){ try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return false; } private static Map initUI(){ System.out.println("欢迎使用该系统,请输入你的用户名和密码"); //读取String用next(),以空格划分 Scanner s = new Scanner(System.in); System.out.print("用户名:"); // String loginname = s.next(); String loginname = s.nextLine(); System.out.print("密码:"); // String loginpwd = s.next(); String loginpwd = s.nextLine(); //将用户名和密码放到Map集合中 Map userlogin__info = new HashMap<>(); userlogin__info.put("loginname",loginname); userlogin__info.put("loginpwd",loginpwd); //返回Map return userlogin__info; } } // 数据库内容 // drop table if exists t_user; // create table t_user( // id int primary key auto_increment, auto_increment表示自增 // login_name varchar(255) unique , // login_pwd varchar(255), // real_name varchar(255) // ); // insert into t_user(login_name,login_pwd,real_name) values('admin','123','孙子昂'); // insert into t_user(login_name,login_pwd,real_name) values('admin01','123','xx02'); // // select *form t_user;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)