Java項目防止SQL注入的幾種方法總結(jié)
一、什么是SQL注入?
SQL注入即是指web應(yīng)用程序?qū)τ脩糨斎霐?shù)據(jù)的合法性沒有判斷或過濾不嚴,攻擊者可以在web應(yīng)用程序中事先定義好的查詢語句的結(jié)尾上添加額外的SQL語句,在管理員不知情的情況下實現(xiàn)非法操作,以此來實現(xiàn)欺騙數(shù)據(jù)庫服務(wù)器執(zhí)行非授權(quán)的任意查詢,從而進一步得到相應(yīng)的數(shù)據(jù)信息。
SQL案列
String sql = "delete from table1 where id = " + "id";
這個id從請求參數(shù)中獲取,若參數(shù)被拼接為:
1001 or 1 = 1
最執(zhí)行語句變?yōu)椋?/p>
String sql = "delete from table1 where id = 1001 or 1 = 1";
此時,數(shù)據(jù)庫的數(shù)據(jù)都會被清空掉,后果非常嚴重
二、Java項目防止SQL注入方式
這里總結(jié)4種:
- PreparedStatement防止SQL注入
- mybatis中#{}防止SQL注入
- 對請求參數(shù)的敏感詞匯進行過濾
- nginx反向代理防止SQL注入
1、PreparedStatement防止SQL注入
PreparedStatement具有預(yù)編譯功能,以上述SQL為例
使用PreparedStatement預(yù)編譯后的SQL為:
delete from table1 where id= ?
此時SQL語句結(jié)構(gòu)已固定,無論"?"被替換為任何參數(shù),SQL語句只認為where后面只有一個條件,當再傳入 1001 or 1 = 1時,語句會報錯,從而達到防止SQL注入效果
2、mybatis中#{}防止SQL注入
mybatis中#{}表達式防止SQL注入與PreparedStatement類似,都是對SQL語句進行預(yù)編譯處理
注意:
#{} :參數(shù)占位符
${} :拼接替換符,不能防止SQL注入,一般用于
- 傳入數(shù)據(jù)庫對象(如:數(shù)據(jù)庫名稱、表名)
- order by 后的條件
3、對請求參數(shù)的敏感詞匯進行過濾
這里是springboot的寫法,如下:
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.util.Enumeration;
/**
* @Auther: 睡竹
* @Date: 2023/03/07
* @Description: sql防注入過濾器
*/
@WebFilter(urlPatterns = "/*",filterName = "sqlFilter")
@Configuration
public class SqlFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
/**
* @description sql注入過濾
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest request = servletRequest;
ServletResponse response = servletResponse;
// 獲得所有請求參數(shù)名
Enumeration<String> names = request.getParameterNames();
String sql = "";
while (names.hasMoreElements()){
// 得到參數(shù)名
String name = names.nextElement().toString();
// 得到參數(shù)對應(yīng)值
String[] values = request.getParameterValues(name);
for (int i = 0; i < values.length; i++) {
sql += values[i];
}
}
if (sqlValidate(sql)) {
//TODO 這里直接拋異常處理,前后端交互項目中,請把錯誤信息按前后端"數(shù)據(jù)返回的VO"對象進行封裝
throw new IOException("您發(fā)送請求中的參數(shù)中含有非法字符");
} else {
filterChain.doFilter(request,response);
}
}
/**
* @description 匹配效驗
*/
protected static boolean sqlValidate(String str){
// 統(tǒng)一轉(zhuǎn)為小寫
String s = str.toLowerCase();
// 過濾掉的sql關(guān)鍵字,特殊字符前面需要加\\進行轉(zhuǎn)義
String badStr =
"select|update|and|or|delete|insert|truncate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|table|"+
"char|declare|sitename|xp_cmdshell|like|from|grant|use|group_concat|column_name|" +
"information_schema.columns|table_schema|union|where|order|by|" +
"'\\*|\\;|\\-|\\--|\\+|\\,|\\//|\\/|\\%|\\#";
//使用正則表達式進行匹配
boolean matches = s.matches(badStr);
return matches;
}
@Override
public void destroy() {}
}4、nginx反向代理防止SQL注入
越來越多網(wǎng)站使用nginx進行反向代理,該層我們也可以進行防止SQL注入配置。
將下面的Nginx配置文件代碼放入到server塊中,然后重啟Nginx即可
if ($request_method !~* GET|POST) { return 444; }
#使用444錯誤代碼可以更加減輕服務(wù)器負載壓力。
#防止SQL注入
if ($query_string ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|javascript|alert|webscan|dbappsecurity|style|confirm\(|innerhtml|innertext)(.*)$) { return 555; }
if ($uri ~* (/~).*) { return 501; }
if ($uri ~* (\\x.)) { return 501; }
#防止SQL注入
if ($query_string ~* "[;'<>].*") { return 509; }
if ($request_uri ~ " ") { return 509; }
if ($request_uri ~ (\/\.+)) { return 509; }
if ($request_uri ~ (\.+\/)) { return 509; }
#if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|\*|\')(.*)$ ) { return 503; }
#防止SQL注入
if ($request_uri ~* "(cost\()|(concat\()") { return 504; }
if ($request_uri ~* "[+|(%20)]union[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504; }
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { return 505; }
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "proc/self/environ") { return 505; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") { return 505; }
if ($query_string ~ "base64_(en|de)code\(.*\)") { return 505; }
if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { return 506; }
if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507; }
if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507; }
if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507; }
if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507; }
#這里大家根據(jù)自己情況添加刪減上述判斷參數(shù),cURL、wget這類的屏蔽有點兒極端了,但要“寧可錯殺一千,不可放過一個”。
if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|wget|curl|Java|python) { return 508; }
#同上,大家根據(jù)自己站點實際情況來添加刪減下面的屏蔽攔截參數(shù)。
if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508; }
if ($http_user_agent ~* "GetWeb!") { return 508; }
if ($http_user_agent ~* "Go!Zilla") { return 508; }
if ($http_user_agent ~* "Download Demon") { return 508; }
if ($http_user_agent ~* "Indy Library") { return 508; }
if ($http_user_agent ~* "libwww-perl") { return 508; }
if ($http_user_agent ~* "Nmap Scripting Engine") { return 508; }
if ($http_user_agent ~* "~17ce.com") { return 508; }
if ($http_user_agent ~* "WebBench*") { return 508; }
if ($http_user_agent ~* "spider") { return 508; } #這個會影響國內(nèi)某些搜索引擎爬蟲,比如:搜狗
#攔截各惡意請求的UA,可以通過分析站點日志文件或者waf日志作為參考配置。
if ($http_referer ~* 17ce.com) { return 509; }
#攔截17ce.com站點測速節(jié)點的請求,所以明月一直都說這些測速網(wǎng)站的數(shù)據(jù)僅供參考不能當真的。
if ($http_referer ~* WebBench*") { return 509; }
#攔截WebBench或者類似壓力測試工具,其他工具只需要更換名稱即可。總結(jié)
到此這篇關(guān)于Java項目防止SQL注入的幾種方法總結(jié)的文章就介紹到這了,更多相關(guān)Java防止SQL注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java開發(fā)druid數(shù)據(jù)連接池maven方式簡易配置流程示例
本篇文章主要為大家介紹了java開發(fā)中druid數(shù)據(jù)連接池maven方式的簡易配置流程示例,文中附含詳細的代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
關(guān)于Object中equals方法和hashCode方法判斷的分析
今天小編就為大家分享一篇關(guān)于關(guān)于Object中equals方法和hashCode方法判斷的分析,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01
JAVAEE Filter 過濾器設(shè)置是否緩存實例詳解
網(wǎng)頁中,每次的客戶端訪問服務(wù)器,有部分不用重復(fù)請求的,這樣可以減輕服務(wù)器的工作量。那么如何設(shè)置客戶端是否都緩存呢?接下來通過本文給大家介紹JAVAEE Filter 過濾器設(shè)置是否緩存的實例,感興趣的朋友一起學(xué)習(xí)吧2016-05-05
Maven將代碼及依賴打成一個Jar包的方式詳解(最新推薦)
這篇文章主要介紹了Maven將代碼及依賴打成一個Jar包的方式,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-05-05

