一、SQL预编译:从根源防御SQL注入攻击
SQL注入是Web安全中最常见且危害极大的攻击方式,攻击者通过构造恶意SQL语句注入参数,篡改原有SQL逻辑,实现越权查询、数据篡改甚至数据库拖库。SQL预编译(PreparedStatement) 是防御SQL注入的核心手段,通过提前编译SQL执行逻辑,彻底阻断恶意参数对SQL结构的篡改。
1. 不安全的SQL写法(存在注入风险)
直接拼接字符串构造SQL语句,攻击者可通过参数注入恶意SQL片段(如 ' or 1=1 --),篡改查询逻辑:
java
// 危险:字符串拼接SQL,存在注入风险
String username = request.getParameter("username");
String sql = "select * from user where username = '" + username + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
攻击示例 :当传入 username = ' or 1=1 -- 时,最终执行的SQL变为:
sql
select * from user where username = '' or 1=1 --'
-- 注释掉后续内容,1=1 使条件恒成立,攻击者可查询到所有用户数据。
2. 安全的SQL预编译写法(防御注入)
预编译核心原理:SQL语句骨架(含占位符 ?)提前编译,参数通过占位符传入,仅作为数据处理,不会被解析为SQL逻辑,从根本上杜绝注入。
java
// 安全:预编译SQL,占位符?接收参数
String sql = "select * from user where username = ?";
// 1. 预编译SQL语句(提前编译执行逻辑)
PreparedStatement pstmt = connection.prepareStatement(sql);
// 2. 为占位符赋值(索引从1开始,自动做字符转义)
pstmt.setString(1, username);
// 3. 执行SQL(参数已绑定,无法篡改逻辑)
ResultSet rs = pstmt.executeQuery();
核心优势:
- 预编译SQL仅编译一次,重复执行时复用编译结果,提升执行效率;
- 参数自动转义(如单引号
'转为\'),恶意SQL片段失效; - 适配所有动态参数场景(查询/新增/修改/删除),通用性强。
3. 预编译的工程化实践
- 所有动态参数必须通过
?占位符传入,禁止字符串拼接; - 预编译对象
PreparedStatement使用后及时关闭,避免资源泄漏; - 结合连接池使用,进一步提升预编译的性能优势。
二、Filter过滤器:Web请求的拦截与安全管控
Filter(过滤器)是JavaEE的核心组件,工作在Servlet之前,可对所有Web资源(Servlet/JSP/静态资源)的请求/响应进行拦截、校验、修改,是实现权限控制、安全检测、请求预处理的关键技术,广泛应用于Web安全场景。
1. Filter核心特性与应用场景
- 拦截范围 :可通过路径匹配拦截指定URL、所有请求(
/*)或特定资源; - 核心能力:修改请求参数、校验请求合法性、过滤敏感词汇、控制响应内容;
- 安全场景:权限访问控制、XSS/CSRF检测、Payload攻击特征识别、内存马检测与清理、请求频率限制等。
2. Filter的创建与配置
(1)自定义Filter实现
自定义Filter需实现 javax.servlet.Filter 接口,重写核心生命周期方法:
java
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
// 注解配置:拦截所有请求(/*),也可指定路径如 /admin/*
@WebFilter("/*")
public class SecurityFilter implements Filter {
// 初始化方法:Filter创建时执行,仅执行一次(初始化资源)
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("SecurityFilter初始化");
}
// 核心拦截方法:每次请求匹配时执行,处理请求/响应
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 1. 请求预处理:校验、过滤、修改
System.out.println("拦截请求:" + ((HttpServletRequest) request).getRequestURI());
// 安全检测示例:校验请求来源/参数合法性
String param = request.getParameter("param");
if (param != null && param.contains("<script>")) {
// 拦截XSS攻击请求
response.getWriter().write("非法请求:包含敏感攻击特征");
return; // 终止请求链
}
// 2. 放行请求:交给下一个Filter或Servlet处理
chain.doFilter(request, response);
// 3. 响应后处理:修改响应内容(如需)
System.out.println("响应处理完成");
}
// 销毁方法:Filter销毁时执行,释放资源(如关闭连接、清理缓存)
@Override
public void destroy() {
System.out.println("SecurityFilter销毁");
}
}
(2)配置方式(两种)
方式1:注解配置(@WebFilter)
直接在Filter类上标注 @WebFilter,指定拦截路径,无需修改配置文件,开发效率高:
java
// 拦截/admin/*路径下的所有请求
@WebFilter(urlPatterns = "/admin/*", filterName = "AdminAuthFilter")
方式2:web.xml配置(适用于集中管理)
通过配置文件实现Filter注册与映射,便于多环境切换:
xml
<!-- 注册Filter -->
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>com.security.filter.SecurityFilter</filter-class>
</filter>
<!-- 映射拦截路径 -->
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<!-- 拦截所有请求 -->
<url-pattern>/*</url-pattern>
<!-- 指定拦截的请求方式(可选) -->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
3. Filter拦截流程与安全实践
- 请求链 :多个Filter按配置顺序依次拦截,通过
chain.doFilter()放行,若未放行则终止请求; - 权限控制示例 :拦截
/admin/*请求,校验Session中是否存在管理员标识,无则重定向到登录页; - 内存马检测:在Filter中监控请求的Servlet/Filter加载情况,识别异常内存马特征并清理;
- Payload检测:匹配请求参数/Body中的攻击Payload(如SQL注入、命令执行特征),拦截恶意请求。
三、Listener监听器:Web容器事件的监控与响应
Listener(监听器)用于监听JavaEE容器中的域对象事件(创建/销毁、属性修改),可在事件发生前后执行自定义逻辑,是实现容器监控、安全审计、内存马检测的重要技术,常与Filter配合构建完整的Web安全体系。
1. Listener核心监听对象与场景
| 监听对象 | 监听事件 | 安全应用场景 |
|---|---|---|
| ServletContext | 上下文创建/销毁、属性增删改 | 全局配置加载、内存马检测、容器启动审计 |
| HttpSession | 会话创建/销毁、属性增删改 | 会话劫持检测、在线用户统计、权限校验 |
| ServletRequest | 请求创建/销毁、属性增删改 | 请求溯源、参数审计、攻击行为记录 |
2. Listener的创建与配置
(1)自定义监听器实现
以监听HttpSession(会话)为例,实现 HttpSessionListener 接口,监控会话创建/销毁:
java
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
// 注解配置监听器
@WebListener
public class SessionSecurityListener implements HttpSessionListener {
// 会话创建时触发(用户首次访问创建Session)
@Override
public void sessionCreated(HttpSessionEvent se) {
String sessionId = se.getSession().getId();
String clientIp = se.getSession().getServletContext().getAttribute("clientIp");
System.out.println("新会话创建:sessionId=" + sessionId + ",客户端IP=" + clientIp);
// 安全审计:记录会话创建日志,检测异常IP/会话频率
}
// 会话销毁时触发(超时/手动销毁)
@Override
public void sessionDestroyed(HttpSessionEvent se) {
String sessionId = se.getSession().getId();
System.out.println("会话销毁:sessionId=" + sessionId);
// 清理会话关联资源,记录会话销毁日志
}
}
(2)配置方式
方式1:注解配置(@WebListener)
直接在监听器类上标注 @WebListener,自动注册到容器,无需额外配置。
方式2:web.xml配置
xml
<listener>
<listener-class>com.security.listener.SessionSecurityListener</listener-class>
</listener>
3. Listener安全高级应用
- 内存马检测:通过ServletContextListener监听上下文属性变化,检测异常添加的Filter/Servlet(内存马特征),及时清理;
- 代码审计辅助:监听ServletRequest的参数变化,记录所有请求的参数、来源IP、执行时间,辅助审计攻击行为;
- 会话安全管控:监听Session创建事件,校验SessionId的合法性,检测会话固定攻击(固定SessionId劫持);
- 全局资源监控:通过ServletContextListener监控容器启动时加载的类、配置,识别恶意篡改的配置文件或类文件。
四、访问控制:Filter+Listener+预编译的综合实践
企业级Web安全的访问控制需结合三者能力,形成"请求拦截-事件监控-数据安全"的完整防护体系:
- 请求层(Filter):拦截所有请求,校验权限、检测攻击Payload、过滤敏感参数;
- 事件层(Listener):监控会话/上下文事件,审计异常行为、记录攻击轨迹;
- 数据层(预编译):所有数据库操作使用PreparedStatement,防御SQL注入。
综合防护示例:管理员后台访问控制
- Filter拦截
/admin/*请求,校验Session中的管理员权限,无权限则拒绝访问; - Listener监控Session创建事件,记录管理员登录的IP、时间,检测异地登录;
- 后台数据库操作全部使用预编译SQL,防止管理员接口被注入攻击。
五、核心技术总结
- SQL预编译:防御SQL注入的核心手段,通过PreparedStatement提前编译SQL,参数占位符隔离数据与逻辑,是数据库操作的安全标配;
- Filter过滤器:Web请求的第一道安全防线,可拦截、校验、修改请求/响应,适配权限控制、攻击检测等安全场景;
- Listener监听器:容器事件的监控核心,实现会话、请求、上下文的全生命周期监控,辅助安全审计与异常检测;
- 综合应用:Filter负责请求拦截管控,Listener负责事件审计监控,预编译保障数据层安全,三者结合构建完整的JavaEE Web安全体系。
以上技术是JavaEE安全开发的核心,覆盖从请求接入到数据操作的全流程安全管控,也是企业级Web应用安全防护的基础,掌握其原理与实践可有效提升Web应用的抗攻击能力。