解決SQL注入現象
阿新 • • 發佈:2021-10-26
package com.bjpowernode.jdbc; import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Scanner; /** * @Author:楊青 * @Time:2021/10/26 10:54 * @Description: * 1.解決SQL注入問題 * 只要使用者提供的資訊不參與SQL語句的編譯過程,問題就解決了。 * 即使使用者提供的資訊中含有SQL語句的關鍵字,但是沒有參與編譯,不起作用 * 要想使用者資訊不參與SQL語句的編譯,就必須使用java.sql.PreparedStatement * PreparedStatement是屬於預編譯的資料庫操作物件 * PreparedStatement的原理是:預先對SQL語句的框架進行編譯,然後再給SQL語句傳‘值’ * 2.測試結果: * 使用者名稱:fdsa * 密碼:fdsa' or '1'='1 * 登陸失敗 * 3.解決SQL注入的關鍵是: * 使用者提供的資訊中即使含有sql語句的關鍵字,但是這些關鍵字並沒有參與編譯,不起作用 * 4.對比Statement和PreparedStatement * -Statement存在sql注入問題,PreparedStatement解決了sql注入問題 * -Statement是編譯一次執行一次,Prepared Statement是編譯一次,可執行N次,PreparedStatement效率較高一些 * -PreparedStatement會在編譯階段做型別的安全檢查 * 綜上所述: * PreparedStatement使用較多,只有極少數的情況下需要使用Statement * 5.什麼情況下必須使用Statement? * 業務方面要求必須支援sql注入的時候 * Statement支援sql注入,凡是業務方面要求是需要進行sql語句拼接的,必須使用Statement */ public class JDBCTest07 { public static void main(String[] args) { //初始化一個介面 Map<String,String> userLoginInfo=userinitUI(); //驗證使用者名稱和密碼 boolean loginSuccess=login(userLoginInfo); System.out.println(loginSuccess?"登陸成功!":"登陸失敗!"); } /** * 使用者登陸 * @param userLoginInfo 使用者登陸資訊 * @return false表示失敗,true表示成功 */ private 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; ResultSet rs=null; try { //1.註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //2.獲取連線 conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456"); //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語句 rs=ps.executeQuery(); //5.處理結果集 if(rs.next()){ //登陸成功 loginSuccess=true; } } catch (Exception e) { e.printStackTrace(); }finally { //6.釋放資源 if(rs!=null) try { rs.close(); }catch (SQLException throwables) { throwables.printStackTrace(); } if(ps!=null) try { ps.close(); }catch (SQLException throwables) { throwables.printStackTrace(); } if(conn!=null) try { conn.close(); }catch (SQLException throwables) { throwables.printStackTrace(); } } return loginSuccess; } /** * 初始化使用者介面 * @return 使用者輸入的使用者名稱和密碼等登陸資訊 */ private static Map<String, String> userinitUI() { Scanner scanner=new Scanner(System.in); System.out.print("使用者名稱:"); String loginName=scanner.nextLine(); //得到使用者名稱 System.out.print("密碼:"); String loginPwd=scanner.nextLine(); //得到密碼 Map<String ,String> userLoginInfo=new HashMap<>(); userLoginInfo.put("loginName",loginName); //將loginName組裝到Map中 userLoginInfo.put("loginPwd",loginPwd); //將loginPwd組裝到Map中 return userLoginInfo; } }