日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 最新sql注入原因以及预防方案(易理解)

發布時間:2024/4/19 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 最新sql注入原因以及预防方案(易理解) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前沿

在現有的框架中sql防注入已經做得很好了,我們需要做的就是盡量不要使用sql拼接調用

java sql注入原因以及預防方案(易理解)

1. SQL注入

1.1 原理

SQL注入是通過客戶端的輸入把SQL命令注入到一個應用的數據庫中,從而執行惡意的SQL語句。

1.2 演示

1.2.1 案例1

有一個登錄框,需要輸入用戶名和密碼,然后我們的密碼輸入 'or ‘123’ = '123 這樣的。我們在查詢用戶名和密碼是否正確的時候,本來執行的sql語句是:select * from user where username = ‘’ and password = ‘’. 這樣的sql語句,現在我們輸入密碼是如上這樣的,然后我們會通過參數進行拼接,拼接后的sql語句就是:

select * from user where username = ‘’ and password = ’ ’ or ‘123’ = '123 '; 這樣的了,那么會有一個or語句,只要這兩個有一個是正確的話,就條件成立,因此 123 = 123 是成立的。因此驗證就會被跳過。這只是一個簡單的列子,

1.2.2 案例2

密碼比如是這樣的:’; drop table user;, 這樣的話,那么sql命令就變成了:
select * from user where username = ‘’ and password = ‘’; drop table user;’ , 那么這個時候我們會把user表直接刪除了。

1.3 防范

1.3.1 前端
  • 前端表單進行參數格式控制;
1.3.2 后端
  • 我們可以使用預編譯語句(PreparedStatement,這 樣的話即使我們使用sql語句偽造成參數,到了服務端的時候,這個偽造sql語句的參數也只是簡單的字符,并不能起到攻擊的作用。

  • 使用正則表達式過濾傳入的參數

注意: 永遠也不要把未經檢查的用戶輸入的值直接傳給數據庫

  • java中的驗證字符串是否包含sql的判斷
package cn.javanode.thread;import java.util.regex.Pattern;/*** @author xgt(小光頭)* @version 1.0* @date 2021-1-8 11:48*/ public class CheckSqlDemo {/**正則表達式**/private static String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"+ "(\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";private static Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);private static boolean isValid(String str) {if (sqlPattern.matcher(str).find()){System.out.println("未能通過過濾器:str=" + str);return false;}return true;}public static void main(String[] args) {System.out.println(isValid("tongji_user_add"));}}

補充

PreparedStatement是如何防止SQL注入的?

1. 拼接參數(sql注入)

Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);PreparedStatement preparedStatement = connection.prepareStatement(sql); String param = "'test' or 1=1";String sql = "select file from file where name = " + param; // 拼接SQL參數ResultSet resultSet = preparedStatement.executeQuery();System.out.println(resultSet.next());

輸出結果為true,DB中執行的SQL為

-- 永真條件1=1成為了查詢條件的一部分,可以返回所有數據,造成了SQL注入問題 select file from file where name = 'test' or 1=1

2. setString (防注入)

Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,account);//設置參數preparedStatement.setString(2,password);ResultSet resultSet = preparedStatement.executeQuery();//執行查詢sql,獲取結果集

輸出結果為false,DB中執行的SQL為

select file from file where name = '\'test\' or 1=1'

我們可以看到輸出的SQL是把整個參數用引號包起來,并把參數中的引號作為轉義字符,從而避免了參數也作為條件的一部分

3. 源碼分析

結論

  • preparedStatement.setString 會判斷當前參數的符號是否需要轉義,是的話加的轉義符
  • 如果不需要,則直接加上引號

//完整代碼 public void setString(int parameterIndex, String x) throws SQLException {synchronized (checkClosed().getConnectionMutex()) {// if the passed string is null, then set this column to nullif (x == null) {setNull(parameterIndex, Types.CHAR);} else {checkClosed();int stringLength = x.length();if (this.connection.isNoBackslashEscapesSet()) {// Scan for any nasty chars// 判斷是否需要轉義boolean needsHexEscape = isEscapeNeededForString(x, stringLength);if (!needsHexEscape) {byte[] parameterAsBytes = null;StringBuilder quotedString = new StringBuilder(x.length() + 2);quotedString.append('\'');quotedString.append(x);quotedString.append('\'');if (!this.isLoadDataQuery) {parameterAsBytes = StringUtils.getBytes(quotedString.toString(), this.charConverter, this.charEncoding,this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor());} else {// Send with platform character encodingparameterAsBytes = StringUtils.getBytes(quotedString.toString());}setInternal(parameterIndex, parameterAsBytes);} else {byte[] parameterAsBytes = null;if (!this.isLoadDataQuery) {parameterAsBytes = StringUtils.getBytes(x, this.charConverter, this.charEncoding, this.connection.getServerCharset(),this.connection.parserKnowsUnicode(), getExceptionInterceptor());} else {// Send with platform character encodingparameterAsBytes = StringUtils.getBytes(x);}setBytes(parameterIndex, parameterAsBytes);}return;}

總結

以上是生活随笔為你收集整理的java 最新sql注入原因以及预防方案(易理解)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。