Comment empêcher l'injection SQL dans les projets Java
一、什么是SQL注入
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
SQL案列
String sql = "delete from table1 where id = " + "id";
这个id从请求参数中获取,若参数被拼接为:
1001 or 1 = 1
最执行语句变为:
String sql = "delete from table1 where id = 1001 or 1 = 1";
此时,数据库的数据都会被清空掉,后果非常严重
二、Java项目防止SQL注入方式
这里总结4种:
PreparedStatement防止SQL注入
mybatis中#{}防止SQL注入
对请求参数的敏感词汇进行过滤
nginx反向代理防止SQL注入
1、PreparedStatement防止SQL注入
PreparedStatement具有预编译功能,以上述SQL为例
使用PreparedStatement预编译后的SQL为:
delete from table1 where id= ?
此时SQL语句结构已固定,无论"?"被替换为任何参数,SQL语句只认为where后面只有一个条件,当再传入 1001 or 1 = 1时,语句会报错,从而达到防止SQL注入效果
2、mybatis中#{}防止SQL注入
mybatis中#{}表达式防止SQL注入与PreparedStatement类似,都是对SQL语句进行预编译处理
注意:
#{} :参数占位符
${} :拼接替换符,不能防止SQL注入,一般用于
传入数据库对象(如:数据库名称、表名)
order by 后的条件
3、对请求参数的敏感词汇进行过滤
这里是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; // 获得所有请求参数名 Enumeration<String> names = request.getParameterNames(); String sql = ""; while (names.hasMoreElements()){ // 得到参数名 String name = names.nextElement().toString(); // 得到参数对应值 String[] values = request.getParameterValues(name); for (int i = 0; i < values.length; i++) { sql += values[i]; } } if (sqlValidate(sql)) { //TODO 这里直接抛异常处理,前后端交互项目中,请把错误信息按前后端"数据返回的VO"对象进行封装 throw new IOException("您发送请求中的参数中含有非法字符"); } else { filterChain.doFilter(request,response); } } /** * @description 匹配效验 */ protected static boolean sqlValidate(String str){ // 统一转为小写 String s = str.toLowerCase(); // 过滤掉的sql关键字,特殊字符前面需要加\\进行转义 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注入
越来越多网站使用nginx进行反向代理,该层我们也可以进行防止SQL注入配置。
将下面的Nginx配置文件代码放入到server块中,然后重启Nginx即可
if ($request_method !~* GET|POST) { return 444; } #使用444错误代码可以更加减轻服务器负载压力。 #防止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; } #这里大家根据自己情况添加删减上述判断参数,cURL、wget这类的屏蔽有点儿极端了,但要“宁可错杀一千,不可放过一个”。 if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|wget|curl|Java|python) { return 508; } #同上,大家根据自己站点实际情况来添加删减下面的屏蔽拦截参数。 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; } #这个会影响国内某些搜索引擎爬虫,比如:搜狗 #拦截各恶意请求的UA,可以通过分析站点日志文件或者waf日志作为参考配置。 if ($http_referer ~* 17ce.com) { return 509; } #拦截17ce.com站点测速节点的请求,所以明月一直都说这些测速网站的数据仅供参考不能当真的。 if ($http_referer ~* WebBench*") { return 509; } #拦截WebBench或者类似压力测试工具,其他工具只需要更换名称即可。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Java est un langage de programmation populaire qui peut être appris aussi bien par les développeurs débutants que par les développeurs expérimentés. Ce didacticiel commence par les concepts de base et progresse vers des sujets avancés. Après avoir installé le kit de développement Java, vous pouvez vous entraîner à la programmation en créant un simple programme « Hello, World ! ». Une fois que vous avez compris le code, utilisez l'invite de commande pour compiler et exécuter le programme, et « Hello, World ! » s'affichera sur la console. L'apprentissage de Java commence votre parcours de programmation et, à mesure que votre maîtrise s'approfondit, vous pouvez créer des applications plus complexes.

Les capsules sont des figures géométriques tridimensionnelles, composées d'un cylindre et d'un hémisphère aux deux extrémités. Le volume de la capsule peut être calculé en ajoutant le volume du cylindre et le volume de l'hémisphère aux deux extrémités. Ce tutoriel discutera de la façon de calculer le volume d'une capsule donnée en Java en utilisant différentes méthodes. Formule de volume de capsule La formule du volume de la capsule est la suivante: Volume de capsule = volume cylindrique volume de deux hémisphères volume dans, R: Le rayon de l'hémisphère. H: La hauteur du cylindre (à l'exclusion de l'hémisphère). Exemple 1 entrer Rayon = 5 unités Hauteur = 10 unités Sortir Volume = 1570,8 unités cubes expliquer Calculer le volume à l'aide de la formule: Volume = π × r2 × h (4

Spring Boot simplifie la création d'applications Java robustes, évolutives et prêtes à la production, révolutionnant le développement de Java. Son approche "Convention sur la configuration", inhérente à l'écosystème de ressort, minimise la configuration manuelle, allo

Java Made Simple : Guide du débutant sur la puissance de programmation Introduction Java est un langage de programmation puissant utilisé dans tout, des applications mobiles aux systèmes d'entreprise. Pour les débutants, la syntaxe de Java est simple et facile à comprendre, ce qui en fait un choix idéal pour apprendre la programmation. Syntaxe de base Java utilise un paradigme de programmation orienté objet basé sur les classes. Les classes sont des modèles qui organisent ensemble les données et les comportements associés. Voici un exemple simple de classe Java : publicclassPerson{privateStringname;privateintage;

Une pile est une structure de données qui suit le principe LIFO (dernier dans, premier sorti). En d'autres termes, le dernier élément que nous ajoutons à une pile est le premier à être supprimé. Lorsque nous ajoutons (ou poussons) des éléments à une pile, ils sont placés sur le dessus; c'est-à-dire surtout

Ce guide explore plusieurs méthodes Java pour comparer deux listes de table. Une comparaison réussie nécessite que les deux listes aient la même taille et contiennent des éléments identiques. Méthodes pour comparer les listes d'arraises en Java Plusieurs approches existent pour comparer AR
