编程自学指南:java程序设计开发,Java Web 安全实战(CSRF/XSS/SQL 注入)
一、课程信息
学习目标
- 理解三大主流 Web 攻击的原理与危害
- 掌握代码级防御措施与框架级解决方案
- 能在项目中修复漏洞并预防安全风险
- 理解安全措施与其他 Web 技术的协作关系
二、课程导入:Web 安全的重要性
🌰 生活类比
- Web 应用 如同银行:
- CSRF:黑客偷用你的银行卡转账(伪装你的操作)
- XSS:在银行填单处放假表格窃取信息
- SQL 注入:直接篡改银行数据库记录
三、CSRF 攻击与防御(25 分钟)
🔍 1. 攻击原理
跨站请求伪造(Cross-Site Request Forgery)
- 核心:攻击者诱导用户执行非预期操作
- 场景:用户已登录银行网站,访问恶意图片触发转账
🔥 2. 攻击演示(易受攻击的代码)
转账 Servlet
@WebServlet("/transfer")
public class TransferServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String toAccount = req.getParameter("toAccount");
double amount = Double.parseDouble(req.getParameter("amount"));
// 模拟转账(无 CSRF 防护)
bankService.transfer(req.getSession().getAttribute("user"), toAccount, amount);
resp.getWriter().write("转账成功");
}
}
恶意页面
<img src="https://bank.com/transfer?toAccount=黑客账户&amount=1000">
🔧 3. 防御措施
✅ 方案 1:CSRF Token
// 生成 Token(在表单页面)
HttpSession session = req.getSession();
String csrfToken = UUID.randomUUID().toString();
session.setAttribute("csrfToken", csrfToken);
req.setAttribute("csrfToken", csrfToken);
<form action="/transfer" method="post">
<input type="hidden" name="csrfToken" value="${csrfToken}">
转账账户:<input type="text" name="toAccount"><br>
金额:<input type="number" name="amount"><br>
<input type="submit" value="转账">
</form>
// 验证 Token(在转账 Servlet)
String token = req.getParameter("csrfToken");
if (!token.equals(session.getAttribute("csrfToken"))) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "非法请求");
return;
}
✅ 方案 2:Referer 检查
String referer = req.getHeader("Referer");
if (!referer.startsWith(req.getScheme() + "://" + req.getServerName())) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "来源不合法");
}
四、XSS 攻击与防御
🔍 1. 攻击原理
跨站脚本攻击(Cross-Site Scripting)
- 核心:攻击者在网页中注入恶意 JavaScript
- 分类:
✅ 反射型(非持久化):攻击代码随请求发送
✅ 存储型(持久化):攻击代码存入数据库
🔥 2. 攻击演示
反射型 XSS(留言板)
@WebServlet("/message")
public class MessageServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String message = req.getParameter("message");
resp.getWriter().write("<h1>" + message + "</h1>"); // 未转义输出
}
}
恶意请求:
/message?message=<script>alert('XSS')</script>
存储型 XSS(博客评论)
@WebServlet("/comment")
public class CommentServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String content = req.getParameter("content");
commentDao.save(content); // 直接存入数据库
resp.sendRedirect("/blog");
}
}
🔧 3. 防御措施
✅ 方案 1:输出转义
import org.apache.commons.lang3.StringEscapeUtils;
String safeMessage = StringEscapeUtils.escapeHtml4(message);
resp.getWriter().write("<h1>" + safeMessage + "</h1>");
✅ 方案 2:输入过滤
String content = req.getParameter("content");
// 过滤掉 <script> 标签
content = content.replaceAll("<script>", "").replaceAll("</script>", "");
✅ 框架支持(Spring MVC)
@PostMapping("/comment")
public String addComment(@RequestParam String content) {
// 自动转义(Spring 默认开启)
return "redirect:/blog";
}
五、SQL 注入攻击与防御
🔍 1. 攻击原理
通过构造恶意 SQL 语句窃取或破坏数据
- 核心:拼接 SQL 语句时未过滤用户输入
🔥 2. 攻击演示(易受攻击的代码)
public User login(String username, String password) {
String sql = "SELECT * FROM users WHERE username = '" + username
+ "' AND password = '" + password + "'";
// 使用 Statement 执行(危险!)
ResultSet rs = stmt.executeQuery(sql);
// ...
}
恶意输入:
username: ' OR '1'='1 --
password: 任意值
🔧 3. 防御措施
✅ 方案 1:预编译语句(PreparedStatement)
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
✅ 方案 2:ORM 框架(Hibernate)
@Query("FROM User WHERE username = :username AND password = :password")
User findByUsernameAndPassword(@Param("username") String username,
@Param("password") String password);
✅ 方案 3:参数校验
if (username.contains("'") || password.contains("'")) {
throw new IllegalArgumentException("非法字符");
}
六、关联知识:安全与其他技术
🔗 1. 与 Filter 的协作(统一 XSS 过滤)
@WebFilter("/*")
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = new XssHttpServletRequestWrapper(req);
chain.doFilter(request, res);
}
}
🔗 2. 与 Session 的协作(CSRF Token 存储)
// 在 Filter 中生成 Token 并存入 Session
HttpSession session = request.getSession();
if (session.getAttribute("csrfToken") == null) {
session.setAttribute("csrfToken", UUID.randomUUID().toString());
}
七、课堂练习
练习 1:修复 CSRF 漏洞
任务:
- 在现有的转账功能中添加 CSRF Token 验证
- 测试恶意页面是否还能触发转账
练习 2:防御 XSS 攻击
任务:
- 修改留言板 Servlet,对用户输入进行 HTML 转义
- 测试注入
<script>
标签是否还能执行
八、课程总结
知识图谱:
Web 安全三大攻击
↳ CSRF:
✅ 原理:伪装用户请求
✅ 防御:Token/Referer 检查
↳ XSS:
✅ 原理:注入恶意脚本
✅ 防御:转义/过滤
↳ SQL 注入:
✅ 原理:拼接恶意 SQL
✅ 防御:预编译/ORM
口诀记忆:
“CSRF 要 Token,XSS 转义牢,
SQL 注入预编译,安全编码要记牢,
Filter 来统一管,框架工具用起来,
安全漏洞早发现,Web 应用稳如山!”
九、课后作业
必做 1:SQL 注入实验
要求:
- 编写一个存在 SQL 注入漏洞的登录功能
- 使用预编译语句进行修复
- 对比两种方式的安全性
必做 2:综合漏洞修复
任务:
- 给定一个存在 CSRF、XSS、SQL 注入漏洞的 Web 应用
- 分析漏洞位置并逐一修复