Java Web 认证授权安全概览 — 框架识别、组件版本与审计清单

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 @EnableWebSecuritySecurityFilterChain@PreAuthorize SecurityConfig.java
Apache Shiro shiro.ini@RequiresAuthenticationSecurityUtils shiro.inispring-shiro.xml
JWT 独立实现 io.jsonwebtokenJwts.parser()Bearer Token application.yml
自定义 Filter implements FilterdoFilter() web.xml@WebFilter
自定义 Interceptor implements HandlerInterceptorpreHandle() 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() 完全移除安全机制 vs permitAll() 仅跳过认证
  • @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() vs getServletPath()
  • JWT 算法混淆、签名验证缺失
  • 水平/垂直越权(IDOR)

防御原则

  • 纵深防御:不依赖单层保护,Filter → Interceptor → AOP 层层把关
  • 认证+授权必须同时存在preHandle 不能只检查登录状态就 return true
  • 最小权限:每个接口只授予完成功能所需的最小权限
  • 持续更新:框架和依赖保持最新,关注安全公告
  • 审计驱动:使用本文提供的脚本定期扫描危险模式
  • 安全默认:Cookie 必须 Secure + HttpOnly + SameSite,Token 必须短过期 + 签名验证

没有银弹,只有持续的关注和不断的加固。


参考资源


免责声明:本文仅供安全研究和学习交流使用,请勿用于非法用途。对他人系统进行未授权的渗透测试属于违法行为。

改变就是好事。