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
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.
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.