ShiroFilterFactoryBean分析
创建核心Filter
同其他框架一样,都有个切入点,这个核心Filter就是拦截所有请求的。
通过web.xml中配置的Filer进入,执行init方法获取这个instance,调用下面的createInstance方法创建核心Filter:
protected AbstractShiroFilter createInstance() throws Exception {
log.debug("Creating Shiro Filter instance.");
SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}
if (!(securityManager instanceof WebSecurityManager)) {
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}
FilterChainManager manager = createFilterChainManager();
//Expose the constructed FilterChainManager by first wrapping it in a
// FilterChainResolver implementation. The AbstractShiroFilter implementations
// do not know about FilterChainManagers - only resolvers:
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
//Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
//FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
//here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
//injection of the SecurityManager and FilterChainResolver:
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}
createFilterChainManager方法比较重要,包含以下必要操作:
DefaultFilterChainManager对象的创建
defaultFilters的获取和相关url的填充
自定义filters的获取和相关url的填充
获取FilterChainDefinitionMap (这个就是配置文件中的filterChainDefinitions的映射关系)
- 对url和权限的映射关系作处理
默认的DefaultFilter枚举中包含以下filter类:
anon(AnonymousFilter.class),
authc(FormAuthenticationFilter.class),
authcBasic(BasicHttpAuthenticationFilter.class),
logout(LogoutFilter.class),
noSessionCreation(NoSessionCreationFilter.class),
perms(PermissionsAuthorizationFilter.class),
port(PortFilter.class),
rest(HttpMethodPermissionFilter.class),
roles(RolesAuthorizationFilter.class),
ssl(SslFilter.class),
user(UserFilter.class);
执行doFilter方法
看下内部类 SpringShiroFilter:
private static final class SpringShiroFilter extends AbstractShiroFilter {
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
super();
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
}
在org.apache.shiro.web.servlet.OncePerRequestFilter中实现了doFilter方法:
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
if ( request.getAttribute(alreadyFilteredAttributeName) != null ) {
log.trace("Filter '{}' already executed. Proceeding without invoking this filter.", getName());
filterChain.doFilter(request, response);
} else //noinspection deprecation
if (/* added in 1.2: */ !isEnabled(request, response) ||
/* retain backwards compatibility: */ shouldNotFilter(request) ) {
log.debug("Filter '{}' is not enabled for the current request. Proceeding without invoking this filter.",
getName());
filterChain.doFilter(request, response);
} else {
// Do invoke this filter...
log.trace("Filter '{}' not yet executed. Executing now.", getName());
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
try {
doFilterInternal(request, response, filterChain);
} finally {
// Once the request has finished, we're done and we don't
// need to mark as 'already filtered' any more.
request.removeAttribute(alreadyFilteredAttributeName);
}
}
}
三种情况,分为两条路线:
1. filterChain.doFilter(request, response); 直接放行
2. doFilterInternal(request, response, filterChain); 走子类实现
在org.apache.shiro.web.servlet.AbstractShiroFilter实现doFilterInternal:
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)
throws ServletException, IOException {
Throwable t = null;
try {
final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
final ServletResponse response = prepareServletResponse(request, servletResponse, chain);
final Subject subject = createSubject(request, response);
//noinspection unchecked
subject.execute(new Callable() {
public Object call() throws Exception {
updateSessionLastAccessTime(request, response);
executeChain(request, response, chain);
return null;
}
});
} catch (ExecutionException ex) {
t = ex.getCause();
} catch (Throwable throwable) {
t = throwable;
}
if (t != null) {
if (t instanceof ServletException) {
throw (ServletException) t;
}
if (t instanceof IOException) {
throw (IOException) t;
}
//otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:
String msg = "Filtered request failed.";
throw new ServletException(msg, t);
}
}
将HttpServletRequest和HttpServletResponse包装成shiro自己的ShiroHttpServletRequest和ShiroHttpServletResponse。
利用包装后的对象创建Subject。
然后是执行subject的execute的方法。
protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain)
throws IOException, ServletException {
FilterChain chain = getExecutionChain(request, response, origChain);
chain.doFilter(request, response);
}
获取的FilterChain是一个代理的ProxiedFilterChain,持有自己的Filter集合,重写doFilter方法:取自己持有的Filter集合,一个个执行其doFilter方法,当所有的Filter都执行完后,再执行servlet的FilterChain。
后面的过程就是一个原始的FilterChain的执行过程。
可以想象,原生的Filter链似乎也是这样一个执行过程,遍历web.xml中配置的所有Filter。
整个过程就是代理模式的运用。
ShiroFilterFactoryBean分析的更多相关文章
- shiro实现无状态的会话,带源码分析
转载请在页首明显处注明作者与出处 朱小杰 http://www.cnblogs.com/zhuxiaojie/p/7809767.html 一:说明 在网上都找不到相关的信息,还是翻了大半天 ...
- Spring-shiro源码陶冶-DelegatingFilterProxy和ShiroFilterFactoryBean
阅读源码有助于陶冶情操,本文旨在简单的分析shiro在Spring中的使用 简单介绍 Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能 web.xml配置Shiro环 ...
- Shiro源码分析
1.入口类:AbstractAuthenticator 用户输入的登录信息经过其authenticate方法: public final AuthenticationInfo authenticate ...
- Shiro的Filter机制详解---源码分析
Shiro的Filter机制详解 首先从spring-shiro.xml的filter配置说起,先回答两个问题: 1, 为什么相同url规则,后面定义的会覆盖前面定义的(执行的时候只执行最后一个). ...
- Shiro的Filter机制详解---源码分析(转)
Shiro的Filter机制详解 首先从spring-shiro.xml的filter配置说起,先回答两个问题: 1, 为什么相同url规则,后面定义的会覆盖前面定义的(执行的时候只执行最后一个). ...
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- 火焰图分析openresty性能瓶颈
注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...
- 一起来玩echarts系列(一)------箱线图的分析与绘制
一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...
- 应用工具 .NET Portability Analyzer 分析迁移dotnet core
大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...
随机推荐
- 【Android】Android之USB
[转载请注明出处] 首先介绍一个概念:USB Host and Accessory Android通过两种模式支持一系列的USB外围设备和Android USB附件(实现了Android附件协议的硬件 ...
- Deep learning with Theano 官方中文教程(翻译)(三)——多层感知机(MLP)
关于更多的http://deeplearning.net/tutorial/的翻译还有学习笔记会陆续整理传到博客. 供大家相互交流和学习,本人水平有限,若有各种大小错误,还请巨牛大牛小牛微牛们立马拍砖 ...
- bzoj 2434 fail tree+dfs序
首先比较明显的是我们可以将字符串组建立ac自动机,那么对于询问s1字符串在s2字符串中出现的次数,就是在以s1结尾为根的fail tree中,子树有多少个节点是s2的节点,这样我们处理fail tre ...
- linux安装(Ubuntu)——(二)
centos的安装参考: http://www.runoob.com/linux/linux-install.html Linux 安装(Ubuntu) 虚拟机:虚拟机(Virtual Machine ...
- Centos7编译安装Xen环境(vtpm)
编译xen环境(http://www.lvtao.net/server/574.html#comment-1882): yum update yum groupinstall "Develo ...
- monkey测试===ios-monkey测试工具
iOSmonkey测试工具: crashmonkey 特点: 支持**真机测试.模拟器测试** 支持收集**系统日志(Systemlog)**.**崩溃日志(Crashlog)**.***instru ...
- visual studio 个性化设置
尼马visual studio 的注释建设的真垃圾 Ctrl+K+C Ctrl+K+U, 通过工具->选项->环境->键盘->命令包含中搜索“注释选定内容”,分配成 Ctrl+ ...
- c basic library framework - simplec 2.0.0
前言 - simplec 单元测试 流程介绍 一个关于C基础库 simplec 2.0.0 发布了. 详细的文档介绍请参照 README.md. 说的再多都无用, 抵不上 gdb 一个 b r n. ...
- C 实现有追求的线程池 探究
引言 线程池很普通的老话题,讨论的很多.深入的不多,也就那些基础库中才能见到这种精妙完备的技巧.而本文随大流 想深入简述一种高效控制性强的一种线程池实现. 先引入一个概念, 惊群. 简单举个例子. 春 ...
- 设计模式之笔记--组合模式(Composite)
组合模式(Composite) 定义 组合模式(Composite),将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 组合模式有 ...