Understanding SQL Injection and Prevention Techniques in Java Projects
SQL injection is a critical web security flaw where unsanitized user input can alter database queries, and this article explains its mechanics, demonstrates vulnerable Java code, and outlines four prevention methods—PreparedStatement, MyBatis #{}, request parameter filtering, and Nginx reverse‑proxy rules—complete with code examples.
What is SQL Injection?
SQL injection occurs when a web application fails to properly validate or filter user‑provided data, allowing an attacker to append malicious SQL statements to a predefined query, causing the database to execute unauthorized operations and potentially expose sensitive data.
Example of vulnerable code: String sql = "delete from table1 where id = " + "id"; If the id parameter is taken directly from the request and an attacker supplies 1001 or 1 = 1, the final statement becomes: String sql = "delete from table1 where id = 1001 or 1 = 1"; This condition always evaluates to true, causing the entire table1 to be cleared, which is a severe consequence.
Java Project Prevention Methods
The article summarizes four approaches to prevent SQL injection in Java applications:
PreparedStatement – Uses parameter placeholders ("?") so the SQL structure is fixed and the database treats the input as data, not code.
MyBatis #{} – Similar to PreparedStatement, the #{} syntax creates a prepared statement, while ${} performs raw string substitution and should be avoided for user data.
Request‑parameter filtering – Implements a servlet filter that scans all incoming parameters for dangerous keywords or characters and rejects the request if a match is found.
Nginx reverse‑proxy rules – Configures Nginx to block suspicious request methods, query strings, and user‑agent strings that contain typical injection patterns.
1. PreparedStatement
Using a prepared statement, the SQL becomes: delete from table1 where id = ? Any attempt to inject additional clauses (e.g., 1001 or 1 = 1) will cause a syntax error, preventing the attack.
2. MyBatis #{}
MyBatis’s #{} placeholder works like a prepared statement, safely binding parameters. In contrast, ${} performs direct string replacement and should only be used for non‑user‑controlled values such as table names.
3. Request‑parameter Filtering (Spring Boot Example)
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.util.Enumeration;
@WebFilter(urlPatterns = "/*", filterName = "sqlFilter")
@Configuration
public class SqlFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest request = servletRequest;
ServletResponse response = servletResponse;
Enumeration<String> names = request.getParameterNames();
StringBuilder sql = new StringBuilder();
while (names.hasMoreElements()) {
String name = names.nextElement();
String[] values = request.getParameterValues(name);
for (String v : values) {
sql.append(v);
}
}
if (sqlValidate(sql.toString())) {
throw new IOException("Parameter contains illegal characters");
} else {
filterChain.doFilter(request, response);
}
}
protected static boolean sqlValidate(String str) {
String s = str.toLowerCase();
String badStr = "select|update|and|or|delete|insert|truncate|char|into|substr|ascii|declare|exec|count|master|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|" +
"'\\*|\\;|\\-|\\--|\\+|\\,|\\//|\\/|\\%|\\#";
return s.matches(badStr);
}
@Override
public void destroy() {}
}4. Nginx Reverse‑Proxy Configuration
Place the following directives inside the server block and restart Nginx:
if ($request_method !~* GET|POST) { return 444; }
# Block suspicious query strings
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; }
# Additional filters for URI, user‑agent, referer, etc.These Nginx rules reject requests containing typical injection patterns, malicious user‑agents, or suspicious referers, reducing the attack surface at the network edge.
Source: blog.csdn.net (original article). The remainder of the page contains promotional material for a backend‑focused technical community, which is not part of the instructional content.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
