程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 使用JDBC連接MySQL數據庫--典型案例分析(五)----用戶名密碼驗證功能

使用JDBC連接MySQL數據庫--典型案例分析(五)----用戶名密碼驗證功能

編輯:MySQL綜合教程

使用JDBC連接MySQL數據庫--典型案例分析(五)----用戶名密碼驗證功能


前幾次有網友轉載我的博客也聲稱原創,我實在對這種人很無語耶,我轉載其他人的博客從來都是很尊重的,該是轉載的就寫明了轉載,雖然這裡沒有人去要求,但是這是對只是的一種尊重,對他人的尊重。人與人之間應如此,哪怕情侶之間也是如此(雖然我沒有談戀愛),但是在生活中我看到無論是小情侶還是小兩口,總存在我覺得不尊重對方的地方,這樣並不好。

言歸正傳,這節謝謝如何進行用戶名的驗證功能。

問題:

現去數據庫建個表,建好之後,結構如下圖:

\

好,本案例的詳細要求如下;

1.使用Statement實現用戶名和密碼的驗證功能,並測試用戶名為“wonderq”,密碼為"root"以及用戶名為"chenxin",密碼為“a' OR 'b'='b”是否能登錄成功。

2.使用PreparedStatement實現用戶和密碼的驗證功能,並測試用戶名為"chenxin",密碼為“a' OR 'b'='b”是否能登錄成功。

方案:

實現本案例的方案如下:

1.使用Statement實現用戶名和密碼的驗證功能。實例代碼如下:

 

sql="select * from users where username=' "+username+" ' " and password=' "+password+" ' ";
	System.out.println(sql);
	con=ConnectionSource.getConnection();
	stmt=con.createStatement();
	rs=stmr.executeQuery(sql);

 

上述代碼存在SQL注入的問題,可以使用PreparedStatement來解決SQL注入的問題。

2.使用PreparedStatement實現用戶名和密碼的驗證功能。preparedStatement是Statement的子類,表示預編譯的SQL語句的對象。在使用PreparedStatement對象執行SQL命令時,命令被數據庫編譯和解析,並放入命令緩沖區。緩沖區中的預編譯SQL命令可以重復使用。實例代碼如下所示:

 

sql="select * from users where username=? and password=?";
	con=ConnectionSource.getConnection();
	stmt=con.PrepareStatement(sql);
	stmt=setString(1,username);
	stmt=setString(2,password);
	rs=stmt.executeQuery();

 

使用PreparedStatement來執行SQL語句。在SQL語句中有2個問號,在代碼中要給它們設置值,從左到右,對應,1,2,....而且setxxx的xxx類型與變量類型要一致。

3.關於SQL注入。對於JDBC而言,SQL注入攻擊只對Statement有效,對PreparedStatement是無效的,這是因為PreparedStatement不允許在插入時改變查詢的邏輯結構。如果有一條SQL語句為:

"select * from 表 where 用戶名='用戶名' "

Statement的SQL語句是這樣寫的:

"select * from 表 where 用戶名=' "+變量值+" ' "

而PreparedStatement的SQL語句是這樣寫的:

"select * from 表 where 用戶名=?"

這樣輸入"aa 'or '1'='1' ",使用Statement執行的SQL語句為:

"select * from 表 where 用戶名=' aa 'or '1'='1' "

而使用PreparedStatement是將"' aa 'or '1'='1' "作為一個字符串復制給問號“?”,使其作為"用戶名"字段的對應值,這樣在防止SQL注入。

步驟:

實現本案例需要如下步驟:

步驟一:創建users表,並插入實例數據

在Mysql數據庫中,創建users表,並插入如下實例數據,SQL語句如下所示:

 

CREATE TABLE users(
id NUMERIC(4),
username VARCHAR(30),
password VARCHAR(30)
);
INSERT INTO users(id,username,password) VALUES (1,'wonderq','root');
INSERT INTO users(id,username,password) VALUES (2,'chenxin','sweet');

\

 

步驟二:使用Statement實現驗證用戶名密碼是否存在

新建UserDAO類,在該類中添加login方法,在該方法中使用Statement實現驗證用戶名密碼是否存在的方法,代碼如下所示:

 


package dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class UserDAO { public static void main(String[] args){ UserDAO dao=new UserDAO(); dao.login("wonderq", "root"); } public void login(String username,String password){ Connection con=null; Statement stmt=null; ResultSet rs=null; String sql=null; try { sql="select * from users where username='"+username+"'"+"and password="+"'"+password+"'"; System.out.println("執行的sql語句:"+sql); con=ConnectionSource.getConnection(); stmt=con.createStatement(); rs=stmt.executeQuery(sql); if(rs.next()){ System.out.println("登錄成功!"); }else{ System.out.println("登錄失敗!"); } } catch (SQLException e) { System.out.println("數據庫訪問異常!"); throw new RuntimeException(e); } finally{ try { if(rs!=null){ rs.close(); } if(stmt!=null){ stmt.close(); } if(con!=null){ con.close(); } } catch (SQLException e2) { System.out.println("釋放資源發生異常!"); } } } } 


 



 

步驟三:使用用戶名為“wonderq”,密碼為"root"測試是否能登錄

只用在usersDAO類的主方法加入如下語句:

 

UserDAO dao=new UserDAO();
		dao.login("wonderq", "root");
運行usersDAO類,控制台輸出結果如下:

 

\

從輸入結果可以看出,使用用戶名為“wonderq”,密碼為“root”可以登錄成功,由於用戶名為"wonderq",密碼為"root"在數據庫中是存在的數據,登陸成功符合預期結果。另外,從輸出sql語句來看,最終變量信息替換為實際傳入的參數信息了。

步驟四:測試login方法

在UserDAO的main方法中,使用用戶名為"chenxin",密碼為"a' OR 'b'='b"作為login方法的參數,測試是否能成功登錄,代碼如下所示:

 

UserDAO dao=new UserDAO();
		//dao.login("wonderq", "root");
		dao.login("chenxin", "a' OR 'b'='b");
運行UserDAO類,控制台輸出如下結果:

 

\

從輸出結果來看,使用用戶名為“chenxin”,密碼為"a' OR 'b'='b"可以登錄成功,但是用戶名為"chenxin",密碼為"a' OR 'b'='b"在數據庫中是不存在的數據,登錄成功不符合預期結果,問題出在哪裡呢?

問題出在sql語句上。查看上述控制台輸出結果,可以看出SQL語句的where字句中,使用or關鍵字連接兩個表達式,即or關鍵字後邊的表達式如果返回true。而or關鍵字後面的表達式為" 'b'='b" ,該表達式的返回結果永遠為true,因此,where條件的返回結果一定為true。這種現象在編程中成為SQL注入,是應該避免的編程方式。可以使用PreparedStatement來防止SQL注入。

步驟五:使用PreparedStatement實現驗證用戶名和密碼功能

在UserDAO類中更改login方法,在該方法中使用PreparedStatement執行SQL語句,來實現驗證用戶名密碼功能。代碼如下所示:

 

package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class UserDAO {
		
	public static void main(String[] args){
		UserDAO dao=new UserDAO();
		//dao.login("wonderq", "root");
		dao.login("chenxin", "a' OR 'b'='b");
	}
	public void login(String username,String password){
		Connection con=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		String sql=null;
		try {
			sql="select * from users where username= ? and password= ?";
			System.out.println("執行的sql語句:"+sql);
			con=ConnectionSource.getConnection();
			stmt=con.prepareStatement(sql);
			stmt.setString(1, username);
			stmt.setString(2, password);
			rs=stmt.executeQuery();
			if(rs.next()){
				System.out.println("登錄成功!");
			}else{
				System.out.println("登錄失敗!");
			}
		} catch (SQLException e) {
			System.out.println("數據庫訪問異常!");
			throw new RuntimeException(e);
		}
		finally{
			try {
				if(rs!=null){
					rs.close();
				}
				if(stmt!=null){
					stmt.close();
				}
				if(con!=null){
					con.close();
				}
			} catch (SQLException e2) {
				System.out.println("釋放資源發生異常!");
			}
		}
	}
}

 

步驟六:測試login方法

在UserDAO類的main方法中,使用用戶名為"chenxin",密碼為"a' OR 'b'='b"作為login方法的參數,測試是否能成功登錄,代碼就是上面的,運行之後,控制台輸出結果:

\

從輸出結果來看,登陸失敗。用戶名為"chenxin",密碼為"a' OR 'b'='b"的數據在數據庫users表中是不存在的數據,登錄失敗符合測試的預期,有效的防止了SQL注入的問題。

本節結束~。。下次進入JDBC的高級編程。。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved