Java Web 认证授权安全概览
认证(你是谁)和授权(你能做什么)是 Web 应用安全的基石。Java 生态拥有成熟的框架体系,但配置不当反而会成为灾难的源头。
本文是系列文章的总览篇,提供框架识别、版本速查、加固清单和审计脚本,各主题深入剖析见后续文章。
系列文章导航
| # | 文章 | 内容 |
|---|---|---|
| 1 | 本文 — 安全概览 | 框架识别、CVE 版本速查、加固检查清单、审计脚本 |
| 2 | Spring Security 安全配置与防护实践 | web.ignoring() 陷阱、方法级鉴权、Actuator 安全、OAuth2 |
| 3 | Apache Shiro 安全配置与防护实践 | rememberMe RCE、路径绕过系列、Spring Boot 集成 |
| 4 | JWT 认证安全实践与常见漏洞 | 算法混淆、签名验证、JWE 加密、Token 轮换 |
| 5 | Java Web 鉴权绕过模式深度剖析 | getRequestURI() 绕过、preHandle 缺陷、WAF 对抗 |
| 6 | Java Web 会话管理与 Redis 认证实践 | Session 校验模式、Redis 限流、分布式会话、WebSocket |
一、认证框架识别
在审计或加固 Java Web 应用时,首先需要确定使用了哪个安全框架:
| 框架 | 识别特征 | 配置文件 |
|---|---|---|
| Spring Security | @EnableWebSecurity、SecurityFilterChain、@PreAuthorize |
SecurityConfig.java |
| Apache Shiro | shiro.ini、@RequiresAuthentication、SecurityUtils |
shiro.ini、spring-shiro.xml |
| JWT 独立实现 | io.jsonwebtoken、Jwts.parser()、Bearer Token |
application.yml |
| 自定义 Filter | implements Filter、doFilter() |
web.xml 或 @WebFilter |
| 自定义 Interceptor | implements HandlerInterceptor、preHandle() |
WebMvcConfigurer |
1.1 框架选型指南
| 场景 | 推荐框架 | 原因 |
|---|---|---|
| 企业级 Web 应用 | Spring Security | 生态成熟,与 Spring Boot 无缝集成 |
| 轻量级/非 Spring 项目 | Apache Shiro | 配置简单,无 Spring 依赖 |
| RESTful API | JWT + Spring Security | 无状态,适合分布式和移动端 |
| 遗留系统(Servlet 2.x) | 自定义 Filter | 不引入额外依赖 |
| 微服务网关层 | OAuth2 + Spring Security | 统一认证,Token 中继 |
审计优先级的经验法则:自定义 Filter/Interceptor 实现的认证系统出问题的概率最高,因为缺少框架的成熟保护机制。
二、高危组件版本速查
版本是安全审计的第一关。以下组件版本存在已知漏洞,必须升级:
| 组件 | 漏洞版本 | 关键 CVE | CVSS | 风险 |
|---|---|---|---|---|
| Shiro | < 1.2.5 | CVE-2016-4437 | 9.8 | rememberMe RCE |
| Shiro | 1.2.5 ~ 1.4.1 | SHIRO-721 | 9.8 | Padding Oracle RCE |
| Shiro | < 1.11.0 | CVE-2023-22602 | 7.5 | 路径绕过 |
| Spring Security | < 5.7.12 | CVE-2024-22257 | 8.2 | 授权绕过 |
| Spring Security | 6.4.0 ~ 6.4.3 | CVE-2025-22223 | 7.5 | @PreAuthorize 绕过 |
| Spring Security | < 6.3.8 / 6.4.4 | CVE-2025-22228 | 7.5 | BCrypt 认证绕过 |
| Spring Security | < 6.3.8 / 6.4.4 | CVE-2025-22235 | 7.3 | Actuator 绕过 |
| Spring Security 7 | < 7.0.5 | CVE-2026-22753 | 7.5 | 访问控制绕过 |
| JJWT | < 0.12.6 | CVE-2024-31033 | 5.3 | 密钥弱化 |
| Tomcat | < 9.0.90 | CVE-2025-24813 | 9.8 | 路径等价 RCE |
| Fastjson | < 1.2.83 | CVE-2022-25845 | 8.1 | 反序列化 RCE |
检测命令:
# 查找依赖版本
grep -A1 "shiro" pom.xml | grep version
grep -A1 "spring-security" pom.xml | grep version
grep -A1 "jjwt" pom.xml | grep version
grep -A1 "fastjson" pom.xml | grep version
# 扫描 JAR 文件
find . -name "shiro-core-*.jar" -o -name "spring-security-core-*.jar"
find . -name "fastjson-*.jar" -o -name "jjwt-*.jar"
2.1 漏洞优先级判断
代码审计中发现组件版本不安全的判断逻辑:
发现低版本组件
│
├── CVSS ≥ 9.0 且可远程利用 → 立即报告,P0
│ 例:Shiro 1.2.4 (CVE-2016-4437, 9.8)
│
├── CVSS ≥ 7.0 且需特定配置 → 确认配置条件后报告,P1
│ 例:Spring Security BCrypt (CVE-2025-22228, 7.5)
│
└── CVSS < 7.0 或仅本地利用 → 记录但不阻塞上线,P2
例:JJWT 密钥弱化 (CVE-2024-31033, 5.3)
三、安全加固检查清单
| 检查项 | 风险 | 操作 | 详见 |
|---|---|---|---|
web.ignoring() 使用 |
🔴 | 替换为 permitAll() |
[Spring Security篇] |
@EnableMethodSecurity |
🔴 | SS 6.x 需 @EnableMethodSecurity;SS 5.x 需 @EnableGlobalMethodSecurity(prePostEnabled=true) |
[Spring Security篇] |
| rememberMe 密钥 | 🔴 | 确认非硬编码,使用强随机密钥 | [Shiro篇] |
| Shiro 版本 | 🔴 | ≥ 1.13.0 或 2.0.0+ | [Shiro篇] |
jwsAlgorithm 白名单 |
🔴 | 只接受单一算法(RS256/ES256) | [JWT篇] |
parseClaimsJws vs parseClaimsJwt |
🔴 | 确保始终使用带签名的版本 | [JWT篇] |
| BCrypt 版本 | 🟡 | spring-security-crypto ≥ 6.3.8 | [Spring Security篇] |
| Actuator 暴露 | 🟡 | 独立端口 + 认证 + 最小暴露 | [Spring Security篇] |
| Session Fixation | 🟡 | migrateSession() 或 newSession() |
[会话管理篇] |
| Cookie Secure/HttpOnly | 🟡 | 确认已设置 | [会话管理篇] |
| CORS 白名单 | 🟡 | 不出现 * + allowCredentials=true |
[Spring Security篇] |
| 密码最小长度限制 | 🟡 | 限制 ≤ 72 字符(BCrypt 限制) | [Spring Security篇] |
| Token 过期时间 | 🟡 | Access Token ≤ 15 分钟 | [JWT篇] |
| 路径匹配 | 🟡 | 使用 getServletPath() 而非 getRequestURI() |
[绕过模式篇] |
preHandle 授权检查 |
🟡 | 不能只认证不授权就 return true |
[绕过模式篇] |
| HTTPS 强制 | 🟡 | requiresSecure() |
[Spring Security篇] |
| Redis 认证密码 | 🟡 | 生产环境必须设置 | [会话管理篇] |
| 安全响应头 | 🟢 | CSP、XSS-Protection、X-Frame-Options | [Spring Security篇] |
| 错误信息 | 🟢 | 不向前端暴露框架/版本信息 | 全部 |
四、快速审计脚本
将此脚本放入项目根目录执行,可快速发现高危配置:
#!/bin/bash
# Java Web 认证授权快速审计脚本
# 用法:bash audit.sh /path/to/project
TARGET_DIR="${1:-.}"
echo "╔══════════════════════════════════╗"
echo "║ Java Web 认证授权审计 ║"
echo "╚══════════════════════════════════╝"
echo "目标: $TARGET_DIR"
echo ""
# ========== 1. 依赖版本检查 ==========
echo "┌── 依赖版本检查 ──────────────────┐"
echo "[*] Shiro 版本:"
grep -r "shiro" "$TARGET_DIR"/pom.xml 2>/dev/null | grep -E "version|<shiro" || echo " 未检测到 Shiro 依赖"
fgrep -r "shiro-core-" "$TARGET_DIR" --include="*.jar" 2>/dev/null | head -5
echo ""
echo "[*] Spring Security 版本:"
grep -r "spring-security" "$TARGET_DIR"/pom.xml 2>/dev/null | grep -E "version|<spring-security" || echo " 未检测到 Spring Security 依赖"
echo ""
echo "[*] JWT 库版本:"
grep -r "jjwt\|io.jsonwebtoken" "$TARGET_DIR"/pom.xml 2>/dev/null | grep version || echo " 未检测到 JWT 依赖"
echo ""
echo "[*] Fastjson 版本(高危组件):"
grep -r "fastjson" "$TARGET_DIR"/pom.xml 2>/dev/null | grep version || echo " 未检测到 Fastjson 依赖"
# ========== 2. 高危配置模式 ==========
echo ""
echo "┌── 高危配置模式 ──────────────────┐"
echo "[*] web.ignoring() 使用(路径完全移除安全):"
grep -rn "web\.ignoring()\|WebSecurityCustomizer" "$TARGET_DIR" --include="*.java" 2>/dev/null || echo " 未发现"
echo ""
echo "[*] rememberMe 硬编码密钥(CVE-2016-4437):"
grep -rn "DEFAULT_CIPHER_KEY\|kPH\+bIxk" "$TARGET_DIR" --include="*.java" --include="*.ini" 2>/dev/null || echo " 未发现硬编码密钥"
echo ""
echo "[*] parseClaimsJwt(无签名验证):"
grep -rn "parseClaimsJwt" "$TARGET_DIR" --include="*.java" 2>/dev/null && echo " ⚠️ 警告:parseClaimsJwt 不验证签名,请改用 parseClaimsJws" || echo " 未发现"
echo ""
echo "[*] @EnableMethodSecurity / @EnableGlobalMethodSecurity 缺失检查:"
# 有 @EnableWebSecurity 但没有启用方法安全注解的配置类
grep -rl "@EnableWebSecurity" "$TARGET_DIR" --include="*.java" 2>/dev/null | while read f; do
grep -q "@EnableMethodSecurity\|@EnableGlobalMethodSecurity" "$f" || echo " ⚠️ 文件 $f 有 @EnableWebSecurity 但缺少 @EnableMethodSecurity / @EnableGlobalMethodSecurity"
done
echo ""
echo "[*] preHandle 只认证不授权(return true 无角色检查):"
grep -rn "preHandle" "$TARGET_DIR" --include="*.java" -A5 2>/dev/null | grep "return true" | head -10
grep -rn "getRequestURI.*endsWith\|getRequestURI.*contains\|getRequestURI.*startsWith" "$TARGET_DIR" --include="*.java" 2>/dev/null && echo " ⚠️ 警告:getRequestURI() + 后缀匹配可被分号绕过" || echo " 未发现"
# ========== 3. 密钥与凭证泄露 ==========
echo ""
echo "┌── 密钥与凭证泄露 ────────────────┐"
echo "[*] 代码中的密钥硬编码:"
grep -rn "secretKey\|privateKey\|SECRET\|password\s*=" "$TARGET_DIR" --include="*.java" --include="*.properties" --include="*.yml" 2>/dev/null | grep -v "test\|mock\|example\|#\|//" | head -5
echo ""
echo "[*] Redis 密码配置:"
grep -rn "redis.*password\|spring.redis.password" "$TARGET_DIR" --include="*.properties" --include="*.yml" 2>/dev/null || echo " 未配置 Redis 密码(仅本地开发可接受)"
# ========== 4. JWT 配置检查 ==========
echo ""
echo "┌── JWT 配置检查 ─────────────────┐"
echo "[*] JWT 算法白名单:"
grep -rn "jwsAlgorithms\|JWSAlgorithm\|SignatureAlgorithm" "$TARGET_DIR" --include="*.java" 2>/dev/null || echo " 未发现算法配置"
echo ""
echo "[*] JWT 过期时间配置:"
grep -rn "setExpiration\|expiration.*time\|jwt.*expir" "$TARGET_DIR" --include="*.java" --include="*.properties" --include="*.yml" 2>/dev/null | head -5
echo ""
echo "╔══════════════════════════════════╗"
echo "║ 审计完成 ║"
echo "╚══════════════════════════════════╝"
echo ""
echo "详细分析请参考系列文章:"
echo " Spring Security → Spring Security 安全配置篇"
echo " Shiro → Apache Shiro 安全配置篇"
echo " JWT → JWT 认证安全实践篇"
echo " preHandle Bypass → 鉴权绕过模式篇"
五、总结
Java Web 认证授权的安全问题主要集中在三个层面:
1. 框架误配置(占比最高)
web.ignoring()完全移除安全机制 vspermitAll()仅跳过认证@EnableMethodSecurity忘记启用导致注解静默失效- 过滤器链顺序错误导致精细规则被宽泛规则覆盖
2. 组件漏洞(影响最大)
- Shiro rememberMe 硬编码密钥 (CVE-2016-4437) — CVSS 9.8,一击必杀
- Shiro 路径绕过系列 — 从 1.2.x 到 1.11.0,持续数年
- Spring Security BCrypt 截断、参数化类型注解丢失等
3. 业务逻辑缺陷(最难发现)
preHandle只认证不授权:登录即return true,无角色/权限校验getRequestURI()+ 后缀匹配白名单:;.js/../轻松绕过- URI 解析差异导致鉴权绕过(
getRequestURI()vsgetServletPath()) - JWT 算法混淆、签名验证缺失
- 水平/垂直越权(IDOR)
防御原则:
- 纵深防御:不依赖单层保护,Filter → Interceptor → AOP 层层把关
- 认证+授权必须同时存在:
preHandle不能只检查登录状态就return true - 最小权限:每个接口只授予完成功能所需的最小权限
- 持续更新:框架和依赖保持最新,关注安全公告
- 审计驱动:使用本文提供的脚本定期扫描危险模式
- 安全默认:Cookie 必须 Secure + HttpOnly + SameSite,Token 必须短过期 + 签名验证
没有银弹,只有持续的关注和不断的加固。
参考资源
- Spring Security 官方文档
- Apache Shiro 安全公告
- OWASP Authentication Cheat Sheet
- OWASP Authorization Cheat Sheet
- JWT Security Best Practices (RFC 8725)
- CVE-2016-4437 Shiro rememberMe 反序列化
- Spring Security CVE 公告
- JJWT GitHub
免责声明:本文仅供安全研究和学习交流使用,请勿用于非法用途。对他人系统进行未授权的渗透测试属于违法行为。