Java JDBC 控制檯使用者登入測試 及 登入存在SQL注入的解決
阿新 • • 發佈:2021-07-31
實現功能:
1.使用者登入
2.java連線資料庫驗證,控制檯顯示成功或失敗
idea 新建java空專案,新建測試類LoginTest
public static void main(String[] args) { //初始化一個介面 Map<String,String> userLoginInfo = initUI(); //驗證使用者名稱和密碼 boolean loginSuccess = login(userLoginInfo); //最後輸出結果 System.out.println(loginSuccess?"登陸成功":"登入失敗"); }
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; Statement stmt=null; ResultSet re =null; try { //1.註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //2.獲取連結 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user","root","root"); //3.獲取資料庫操作物件 stmt = conn.createStatement(); //4.執行SQL String sql = "select * from t_user where loginName = '"+loginName+"' and loginPwd = '"+loginPwd+"' "; //以上正好完成了SQL語句的拼接,以下程式碼的含義是傳送SQL語句給DBMS,DBMS進行SQL編譯 re = stmt.executeQuery(sql);//執行查詢,將SQL傳過來 //5.處理結果集 if(re.next()){ //登陸成功 loginSuccess = true; } } catch (Exception e) { e.printStackTrace(); }finally { //6.資源釋放 if(re!=null) { try { re.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt !=null) { try { re.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null) { try { re.close(); } catch (SQLException e) { e.printStackTrace(); } } } return loginSuccess; }
private static Map<String, String> initUI() { Scanner s = new Scanner(System.in); //讀取使用者名稱 System.out.print("使用者名稱:"); String loginName = s.nextLine(); //讀取密碼 System.out.println("密碼:"); String loginPwd =s.nextLine(); //將資料組裝到Map中 Map<String,String> userLoginInfo = new HashMap<>(); userLoginInfo.put("loginName",loginName); userLoginInfo.put("loginPwd",loginPwd); //返回Map return userLoginInfo; }
執行結果:
登陸成功
存在問題 : SQL注入
使用者名稱:qwer
密碼:qwer' or '1'='1
此時能夠能錄成功,這種現象被稱為SQL注入
導致SQL注入的根本原因:
使用者輸入的資訊中含有SQL語句的關鍵字,並且這些關鍵字參與SQL的編譯過程,導致SQL語句的原意被扭曲,進而達到SQL注入
其中
String sql = "select * from t_user where loginName = '"+loginName+"' and loginPwd = '"+loginPwd+"' ";
re = stmt.executeQuery(sql);//執行查詢,將SQL傳過來
上行程式碼正好完成了SQL語句的拼接,下行程式碼的含義是傳送SQL語句給DBMS,DBMS進行SQL編譯,正好將使用者提供的“非法資訊”編譯進去,扭曲了原有SQL語句
解決方法:
只要使用者提供的資訊不參與編譯過程,問題就解決了,使用PrepareStatement替換Statement
新建類LoginTest02
public static void main(String[] args) {
//初始化一個介面
Map<String,String> userLoginInfo = initUI();
//驗證使用者名稱和密碼
boolean loginSuccess = login(userLoginInfo);
//最後輸出結果
System.out.println(loginSuccess?"登陸成功":"登入失敗");
}
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;
//這裡使用prepareStatement(預編譯的資料庫操作物件)
PreparedStatement ps=null;
ResultSet re =null;
try {
//1.註冊驅動
Class.forName("com.mysql.jdbc.Driver");
//2.獲取連結
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user","root","root");
//3.獲取預編譯的資料庫操作物件
String sql = "select * from t_user where loginName = ? and loginPwd = ? ";
//SQL語句的框子。問號是佔位符,不加引號。一號問號接受一個值
// 程式執行到此處,會發送SQL語句框子給DBMS,然後DBMS進行SQL語句的預先編譯
//給佔位符?傳值 (第一個問號下標是1,第二個問號下標是2,JDBC所有下標 從1開始)
//4.執行SQL
ps = conn.prepareStatement(sql);
ps.setString(1,loginName);
ps.setString(2,loginPwd);
re = ps.executeQuery();
//5.處理結果集
if(re.next()){
//登陸成功
loginSuccess = true;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//6.資源釋放
if(re!=null) {
try {
re.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps !=null) {
try {
re.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null) {
try {
re.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return loginSuccess;
}
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中
Map<String,String> userLoginInfo = new HashMap<>();
userLoginInfo.put("loginName",loginName);
userLoginInfo.put("loginPwd",loginPwd);
//返回Map
return userLoginInfo;
}
執行結果:
SQL注入問題解決,登入正常
解決SQL注入問題的關鍵:
使用者提供的資訊中心即使含有SQL語句的關鍵字,但這些關鍵字沒有參與編譯,只要使用者提供的資訊不參與編譯過程,問題就解決了
要想使用者資訊不參與SQL語句的編譯,那麼必須使用java.sql.PreparedStatement
PreparedStatement介面繼承了java.sql.Statement,是屬於預編譯的資料庫操作物件
原理是預先對SQL語句框架進行編譯,然後再給SQL傳值
本文來自部落格園,作者:大星星不見了,轉載請註明原文連結:https://www.cnblogs.com/dxxbjl/p/15084523.html