shiro-web 软件分析
字数 2669 2025-08-20 18:17:58
Apache Shiro Web 模块深入分析与教学文档
1. Shiro-Web 概述
Shiro-Web 是 Shiro-Core 的包装器(wrapper),主要提供与 Servlet 容器的集成能力。其核心特征是"实现一方,调用一方"的设计模式:
- 实现 Filter 接口使 Tomcat 可以调用
- ShiroFilter 调用 WebSubject
- WebSubject 调用 Subject 接口(继承自 shiro-core)
关键特性
-
双向调用关系:
- 主要调用方向:shiro-web → shiro-core
- 特殊情况:shiro-core 也会回调 wrapper 中的实现(如 SessionManager 的两种实现)
-
Session 管理冲突处理:
- Servlet 容器(如 Tomcat)已有 Session 管理实现
- Shiro 提供了自己的 SessionManager
- 开发者需要选择使用哪种 Session 管理方式
2. 架构设计与解耦机制
Shiro-Web 通过继承方式实现与核心模块的解耦:
Servlet容器 → ShiroFilter → WebSubject → WebSecurityManager
这种设计使得:
- shiro-web 不直接依赖 shiro-core
- 大部分逻辑由 shiro-core 实现
- shiro-web 只需关注特定于 Web 的部分
3. Filter 体系结构
3.1 类图结构
OncePerRequestFilter
├── 直接对接 Servlet 容器的 Filter 分支
└── 实际执行过滤逻辑的 Filter 分支
└── AbstractShiroFilter (ShiroFilter)
└── AdviceFilter
└── AccessControlFilter
├── InvalidRequestFilter (封锁恶意请求)
└── UserFilter (允许已知用户访问)
3.2 核心 Filter 详解
OncePerRequestFilter:
doFilter()方法实际逻辑由doFilterInternal()决定(子类实现)- 确保每个请求只被过滤一次
AbstractShiroFilter:
- 初始化:读取解析配置文件
- 核心算法:
- 获取执行链
- 执行过滤操作
AdviceFilter:
- 提供 AOP 风格的"环绕"通知:
preHandle: 请求处理前postHandle: 请求处理后afterCompletion: 请求完成后
AccessControlFilter:
- 访问控制基类
- 主要子类:
InvalidRequestFilter: 封锁恶意请求UserFilter: 仅允许已知用户(已认证或记住我)访问
4. Filter 链管理
4.1 FilterChainManager
管理从可用 Filter 实例池中创建和修改 Filter 链。
关键组件:
NamedFilterList: 装载NameableFilter及其子类的列表NameableFilter: 配置文件中配置的过滤器
4.2 配置示例
[main]
shiro.loginUrl = /login
shiro.successUrl = /loginSuccess
filterName = className
[urls]
/login = authc
/admin = authc, roles[admin]
/user = authc, roles[user]
/** = anon
URL 配置格式:
/some/path/** = myFilter,otherFilter
表示该路径需要经过 myFilter 和 otherFilter 两个过滤器
4.3 默认过滤器
Shiro 提供了一组默认过滤器(如 authc, anon, roles 等),可直接在配置中使用。
5. FilterChainResolver
根据请求 URL 返回对应的 FilterChain。
唯一实现类:PathMatchingFilterChainResolver
工作流程:
- 获取 requestUrl
- 遍历所有 filterChainNames (pathPattern)
- 逐个比对,匹配成功则调用
FilterChainManager.proxy(originalChain, pathPattern)
proxy() 方法详解:
// DefaultFilterChainManager
public FilterChain proxy(FilterChain original, String chainName) {
NamedFilterList configured = getChain(chainName); // 获取配置的过滤器链
if (configured == null) {
throw new IllegalArgumentException("No configured chain under name [" + chainName + "]");
}
return configured.proxy(original); // 代理
}
// SimpleNamedFilterList
public FilterChain proxy(FilterChain orig) {
return new ProxiedFilterChain(orig, this); // 创建代理链
}
6. ProxiedFilterChain 架构
public class ProxiedFilterChain implements FilterChain {
private FilterChain orig; // Servlet 容器原始链
private List<Filter> filters; // Shiro 实际过滤器
private int index = 0; // 当前过滤器索引
public void doFilter(ServletRequest request, ServletResponse response) {
if (this.filters == null || this.filters.size() == this.index) {
// 执行完 Shiro 过滤器后,调用原始链
this.orig.doFilter(request, response);
} else {
// 执行当前 Shiro 过滤器
this.filters.get(this.index++).doFilter(request, response, this);
}
}
}
7. 总体流程
- 请求到达 ShiroFilter (AbstractShiroFilter)
- 通过 FilterChainResolver 获取匹配的 FilterChain
- 创建 ProxiedFilterChain (包装原始 FilterChain 和 Shiro 过滤器)
- 执行 ProxiedFilterChain 的 doFilter 方法:
- 先执行所有 Shiro 过滤器
- 最后执行原始 Servlet 容器过滤器链
- 过滤完成后,请求继续 Servlet 容器的正常处理流程
8. 关键设计模式
-
Wrapper 模式:
- shiro-web 作为 shiro-core 的包装器
- 提供 Web 特定功能,同时重用核心逻辑
-
责任链模式:
- FilterChain 管理多个过滤器的执行顺序
- ProxiedFilterChain 实现过滤器链的代理
-
模板方法模式:
- OncePerRequestFilter 定义算法骨架
- 具体过滤逻辑由子类实现 (doFilterInternal)
-
策略模式:
- FilterChainResolver 提供不同的匹配策略
- 目前只有 PathMatchingFilterChainResolver 实现
9. 最佳实践
-
Session 管理选择:
- 评估是否需要 Shiro 的 SessionManager
- 考虑与容器 Session 的兼容性
-
过滤器配置:
- 合理使用默认过滤器
- 自定义过滤器时继承适当的基类
-
URL 匹配:
- 精确路径优先于通配符
- 注意过滤器顺序的影响
-
性能考虑:
- 避免过于复杂的过滤器链
- 利用 OncePerRequestFilter 避免重复过滤
10. 扩展点
-
自定义 Filter:
- 继承 AccessControlFilter 或 AdviceFilter
- 实现特定的访问控制逻辑
-
自定义 FilterChainResolver:
- 实现不同的 URL 匹配策略
- 如基于正则表达式或其他条件
-
SessionManager 集成:
- 实现自定义 SessionManager
- 集成第三方 Session 存储
11. 常见问题解决方案
-
过滤器不生效:
- 检查 web.xml 配置
- 验证 URL 模式匹配
- 确认过滤器顺序
-
Session 冲突:
- 明确选择 Session 管理方式
- 必要时实现自定义 SessionManager
-
性能问题:
- 减少不必要的过滤器
- 优化 URL 匹配模式
-
安全漏洞:
- 确保使用 InvalidRequestFilter
- 定期更新 Shiro 版本
12. 总结
Shiro-Web 通过精心的设计实现了:
- 与 Servlet 容器的无缝集成
- 与核心模块的清晰解耦
- 灵活的过滤器链管理
- 可扩展的安全控制机制
理解其内部机制有助于:
- 更有效地使用 Shiro 进行 Web 安全防护
- 更快速地定位和解决问题
- 更灵活地进行定制开发