JDBC_08_解决SQL注入问题 (登录和注册)
解决SQL注入问题
-
只要用户提供的信息不参与sql语句的编译过程,那么尽管用户输入的信息中含有sql关键字那么也不会起作用了
-
要想使用户提供信息不参与sql语句的编译过程,那么必须使用 java.sql.PreparedStatement 预编译的数据库操作对象,提前编译sql语句框架
-
PreparedStatement 继承了 Statement
-
PreparedStatement的原理是预先对sql语句框架进行编译,然后再给sql语句传值。
-
将Statement(数据库操作对象) 换为 PreparedStatement(预编译的数据库操作对象)
-
获取预编译数据库连接对象preparedStatement,将sql语句框架预先进行编译。 其中SQL语句中的 一个 ?表示一个占位符,占位符不能用单引号括起来。
- preparedStatement=connection.prepareStatement("select * from t_user where loginName=? and loginPwd=? "); 使用 ?进行占位。
-
给占位符 ? 传值 注意:第一个问号的下标是1 ,第二个问号下标是 2
- preparedStatement.setString(1,loginName); 第一个问号传 loginName - preparedStatement.setString(2,loginPwd); 第二个问号传 loginPwd
-
代码实例:
import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Scanner; /** * 解决sql注入问题 * 只要用户提供的信息不参与sql语句的编译过程,那么尽管用户输入的信息中含有sql关键字那么也不会起作用了 * 要想使用户提供信息不参与sql语句的编译过程,那么必须使用java.sql. PreparedStatement 预编译的数据库操作对象 * PreparedStatement 继承了 Statement * PreparedStatement的原理是预先对sql语句框架进行编译,然后再给sql语句传值 * 将Statement(数据库操作对象) 换为 PreparedStatement(预编译的数据库操作对象) * * */ public class 解决sql注入 { public static void main(String[] args) throws SQLException { //掉用initUI()获取用户名密码 Map<String,String> userLoginInfo=initUI(); //调用register()方法。 //boolean registerSuccess=register(userLoginInfo); //输出结果 //System.out.println(registerSuccess?"注册成功":"注册失败"); //调用logIn()方法。 boolean loginSuccess=login(userLoginInfo); System.out.println(loginSuccess?"登陆成功":"密码错误"); } /** * 用户注册 * @param userLoginInfo 用户登录信息 * @return true成功, false失败 */ private static boolean register(Map<String, String> userLoginInfo) { //创建连接对象 Connection connection=null; Statement statement=null; int count=0; try { //注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接 connection= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai", "root","123456"); //获取数据库操作对象 statement=connection.createStatement(); //执行SQL语句 count=statement.executeUpdate("insert into t_user(loginName,loginPwd,realName)values('"+userLoginInfo.get("loginName")+"','"+userLoginInfo.get("loginPwd")+"',' ') "); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); }finally { if(statement!=null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } if(count==1){ return true; } return false; } /** * 用户登录 * @param userLoginInfo 用户信息 * @return 成功true 失败fslse */ private static boolean login(Map<String, String> userLoginInfo) throws SQLException { //标识 boolean flag=false; //获取用户信息 String loginName=userLoginInfo.get("loginName"); String loginPwd=userLoginInfo.get("loginPwd"); //创建连接对象 Connection connection=null; PreparedStatement preparedStatement=null; //这里使用PreparedStatement(预编译的数据库操作对象) ResultSet resultSet=null; try { //注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接 connection=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai", "root","123456"); //获取预编译数据库连接对象,将sql语句框架预先进行编译。其中一个?表示一个占位符,占位符不能用单引号括起来 preparedStatement=connection.prepareStatement("select * from t_user where loginName=? and loginPwd=?"); //使用?进行占位 //给占位符? 传值 注意:第一个问号的下标是1 ,第二个问号下标是 2 preparedStatement.setString(1,loginName); //第一个问号传 loginName preparedStatement.setString(2,loginPwd); //第二个问号传 loginPwd //执行SQL语句 使用 PreparedStatement,执行sql的使用,不用再传入sql语句,因为前面已经编译过了。 resultSet=preparedStatement.executeQuery(); //处理查询结果集 if(resultSet.next()){ flag=true; } } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); }finally { if(resultSet!=null){ resultSet.close(); } if(preparedStatement!=null){ preparedStatement.close(); } if (connection!=null){ connection.close(); } } return flag; } /** * 初始化用户界面 * @return 返回用户登录信息 */ private static Map<String, String> initUI() { //创建用户信息接收对象 Scanner scanner=new Scanner(System.in); System.out.println("请输入您的用户名:"); String userName=scanner.nextLine(); System.out.println("请输入您的密码:"); String pwd=scanner.nextLine(); //创建一个Map集合用来存放用户输入得用户名和密码 Map<String,String> userLoginInfo=new HashMap<String,String>(); userLoginInfo.put("loginName",userName); userLoginInfo.put("loginPwd",pwd); return userLoginInfo; } }