一、核心知识点总览
-
**SQL预编译(PreparedStatement)** :JavaEE中防御SQL注入的核心机制,通过固定SQL逻辑、参数化传参避免注入攻击;
-
**Filter过滤器**:拦截Web请求/响应,实现权限控制、XSS过滤等安全功能;
-
**Listener监听器**:监听JavaEE域对象(如Session、ServletContext)的事件,用于安全审计、内存马检测等场景。
二、SQL预编译:防御SQL注入的"安全锁"
(一)核心原理
-
**本质**:提前将SQL语句"编译成模板",用户输入仅作为"参数"填充到模板的占位符(`?`)中,不改变SQL原有执行逻辑;
-
**防注入原因**:参数会被数据库自动转义(如特殊字符`'`、`or`等),仅被识别为"数据",而非"SQL代码"。
(二)代码实现(对比不安全写法)
1. 不安全写法(Statement拼接SQL,易注入)
```java
// 风险:直接拼接用户输入,攻击者可注入 `1' union select 1,version(),database()-- `
String sql = "SELECT * FROM news WHERE id=" + userInputId;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql); // 若userInputId含注入代码,SQL逻辑被篡改
```
2. 安全写法(PreparedStatement预编译)
```java
// 1. 定义SQL模板(占位符?表示参数)
String safeSql = "SELECT * FROM news WHERE id=?";
// 2. 预编译SQL(数据库提前解析逻辑,固定执行流程)
PreparedStatement pstmt = conn.prepareStatement(safeSql);
// 3. 绑定参数(第1个?赋值为userInputId,自动转义特殊字符)
pstmt.setString(1, userInputId); // 若参数是数字,用setInt(1, Integer.parseInt(userInputId))
// 4. 执行查询(逻辑已固定,注入代码无效)
ResultSet rs = pstmt.executeQuery();
// 5. 处理结果集(省略)
while (rs.next()) {
System.out.println("新闻标题:" + rs.getString("title"));
}
```
(三)安全价值
-
从"根源"阻断SQL注入:即使攻击者输入`1' or '1'='1`,也会被当作"字符串参数"处理,SQL最终逻辑仍为"查询id等于该字符串的记录";
-
兼容性强:所有关系型数据库(MySQL、Oracle等)均支持PreparedStatement。
三、Filter过滤器:Web请求的"拦截与守卫"
(一)核心作用
Filter是JavaEE的"请求拦截器",可在请求到达Servlet前、响应返回客户端前做自定义处理,典型安全场景:
-
权限控制(如拦截未登录用户访问管理员页面);
-
输入过滤(如XSS、SQL注入Payload检测);
-
敏感信息脱敏(如响应中隐藏手机号、身份证号)。
(二)核心特性
-
**生命周期**:`init()`(应用启动时初始化,仅1次)→ `doFilter()`(每次请求触发,核心逻辑)→ `destroy()`(应用关闭时销毁,仅1次);
-
**执行流程**:请求 → Filter拦截处理 → 放行(`filterChain.doFilter()`)→ 目标Servlet/JSP → 响应 → Filter再次拦截响应 → 返回客户端。
(三)实战案例
案例1:XSS过滤(拦截含`<script>`的请求参数)
```java
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
// 注解配置:拦截访问/test路径的所有请求
@WebFilter("/test")
public class XssFilter implements Filter {
// 1. 过滤器初始化(应用启动时执行1次)
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("XSS过滤器已初始化");
}
// 2. 核心拦截逻辑(每次请求触发)
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
// 转换为HttpServletRequest(获取请求参数需HTTP相关对象)
HttpServletRequest request = (HttpServletRequest) req;
// 获取请求参数code(如用户输入的内容)
String code = request.getParameter("code");
// XSS检测:若含<script>标签,拦截请求
if (code != null && code.contains("<script>")) {
System.out.println("拦截XSS攻击!参数含危险标签:" + code);
resp.getWriter().write("请求含不安全内容,已拦截");
return; // 不放行,直接返回
}
// 无危险内容,放行到下一个Filter/Servlet
chain.doFilter(req, resp);
}
// 3. 过滤器销毁(应用关闭时执行1次)
@Override
public void destroy() {
System.out.println("XSS过滤器已销毁");
}
}
```
案例2:Cookie身份验证(仅允许含`user=admin`的请求访问/admin)
```java
@WebFilter("/admin") // 拦截管理员页面请求
public class AdminFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
Cookie[] cookies = request.getCookies(); // 获取客户端Cookie
boolean isAdmin = false;
if (cookies != null) {
// 遍历Cookie,检查是否有"user=admin"
for (Cookie cookie : cookies) {
if ("user".equals(cookie.getName()) && "admin".equals(cookie.getValue())) {
isAdmin = true;
break;
}
}
}
if (isAdmin) {
chain.doFilter(req, resp); // 管理员,放行
} else {
resp.getWriter().write("非管理员,无访问权限"); // 拦截未授权请求
}
}
// init()和destroy()省略...
}
```
(四)安全场景扩展
-
**Payload检测**:拦截含SQL注入(如`union`、`select`)、命令执行(如`;ls`)的请求参数;
-
**权限控制**:验证请求头中的Token、Session是否有效,拦截未登录用户;
-
**内存马相关**:红队可通过Filter植入内存马(拦截请求执行恶意代码),蓝队可通过Filter监控异常请求。
四、Listener监听器:JavaEE域对象的"事件监控器"
(一)核心作用
Listener用于"监听"JavaEE域对象的**事件**(如对象创建/销毁、属性变化),并在事件触发时执行自定义逻辑,典型场景:
-
监控Session创建/销毁(统计在线用户数);
-
监听ServletContext初始化(加载全局配置、初始化安全组件);
-
安全审计(记录敏感操作的事件日志)。
(二)核心域对象与事件
| 监听器接口 | 监听对象 | 核心事件 |
| ------------ | ---------------- | --------------------------- |
| `HttpSessionListener` | HttpSession | Session创建(`sessionCreated`)、销毁(`sessionDestroyed`) |
| `ServletContextListener` | ServletContext | 应用启动(`contextInitialized`)、关闭(`contextDestroyed`) |
| `ServletRequestListener` | ServletRequest | 请求创建(`requestInitialized`)、销毁(`requestDestroyed`) |
(三)实战案例:监听Session创建与销毁
```java
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
// 注解标记为监听器(无需web.xml配置)
@WebListener
public class SessionListener implements HttpSessionListener {
// 1. 监听Session创建(用户首次访问时触发)
@Override
public void sessionCreated(HttpSessionEvent se) {
// se.getSession():获取当前创建的Session
String sessionId = se.getSession().getId();
System.out.println("监听到新Session创建,ID:" + sessionId);
// 扩展:记录用户登录日志、统计在线用户数
}
// 2. 监听Session销毁(如调用session.invalidate()、Session超时)
@Override
public void sessionDestroyed(HttpSessionEvent se) {
String sessionId = se.getSession().getId();
System.out.println("监听到Session销毁,ID:" + sessionId);
// 扩展:清理用户临时数据、释放资源
}
}
```
配合Servlet触发Session事件
```java
// 1. 创建Session的Servlet(访问/cs触发)
@WebServlet("/cs")
public class CreateSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
req.getSession(); // 获取Session(不存在则创建,触发sessionCreated)
System.out.println("Servlet创建Session");
}
}
// 2. 销毁Session的Servlet(访问/ds触发)
@WebServlet("/ds")
public class DestroySessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
req.getSession().invalidate(); // 销毁Session,触发sessionDestroyed
System.out.println("Servlet销毁Session");
}
}
```
(四)安全场景
-
**代码审计**:监控Session创建/销毁事件,追踪异常会话(如短时间大量创建Session的暴力破解行为);
-
**内存马检测**:监听ServletContext初始化事件,排查是否有未授权的恶意Listener/Filter被注入;
-
**安全日志**:记录请求创建/销毁事件,留存访问轨迹用于事后溯源。
五、总结:三者在JavaEE安全中的协同作用
| 技术 | 核心安全能力 | 典型场景 |
| ---------------- | ------------------------------ | ----------------------------------- |
| SQL预编译 | 防御SQL注入 | 用户登录、数据查询时的参数处理 |
| Filter过滤器 | 请求拦截、权限控制、输入过滤 | XSS过滤、管理员页面访问控制 |
| Listener监听器 | 事件监控、安全审计 | 在线用户统计、Session异常行为检测 |
三者共同构成JavaEE应用的"安全三层防护":**数据层(预编译防注入)→ 请求层(Filter拦截风险)→ 事件层(Listener监控异常)** ,需结合使用以提升整体安全性。