在springMVC中要使用shiro,一般都遵循下面的配置:

applicationContext-shiro.xml

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
..... </bean>

web.xml

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!-- Spring MVC Servlet -->
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/springmvc-common.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

看到这样的配置,难免有些疑问:
1. 这三者是怎样融合到一起的
2. 为什么那个bean的id和filter的name保持一样
3. 为什么配置的bean是一个factoryBean而不是普通的bean

带着这样的疑问,跟踪下启动过程。正向跟踪,即在refresh方法中开展,锁定getBean方法,通过name来追踪shiroFilter,发现关系比较乱,而且费时。于是锁定ShiroFilterFactoryBean的getObject方法,反向追踪,获得了下面的序列图:

重点就是:

配置的监听器启动容器的初始化,完成上面ShiroFilterFactoryBean的创建和维护

servlet触发过滤器Filter的init方法,在initDelegate方法中会getBean(),这个getBean最终会转移到ShiroFilterFactoryBean的getObject方法

上面的问题第二个看源码很容易解决。

在调用DelegatingFilterProxy初始化方法时:

@Override
protected void initFilterBean() throws ServletException {
synchronized (this.delegateMonitor) {
if (this.delegate == null) {
// If no target bean name specified, use filter name.
if (this.targetBeanName == null) {
this.targetBeanName = getFilterName();
}
// Fetch Spring root application context and initialize the delegate early,
// if possible. If the root application context will be started after this
// filter proxy, we'll have to resort to lazy initialization.
WebApplicationContext wac = findWebApplicationContext();
if (wac != null) {
this.delegate = initDelegate(wac);
}
}
}
} protected final String getFilterName() {
return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
} protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}

获取的这个名字将用来追寻之前spring维护的那个bean,并且还要通过它来拿到一个Filter实例。

那么为什么配置的那个bean是一个factoryBean而不是一个普通的bean?

首先shiro是基于过滤器来实现的,配置一个filter是必要的。

但是和spring在一起使用,就要让spirng来管理一些filter依赖的bean,例如安全管理器,还有自己实现的认证和鉴权服务之类。如果shiro直接写一个过滤器,那spring的容器早就启动完了,你这些东西怎么注入。

所以只有提前初始化那些过滤器需要的东西,让他们依附于某个特定类,通过约定来在过滤器的初始化中获取(这个就是前面提到的相同的name)。

那么这个bean可以是普通的bean吗?答案是不可以,毕竟shiro要的这个bean得是一个filter。普通的bean只能获取到它本身的实例,要获取filter那么它必须实现Filter接口。但是创建filter的方法你掌控不了了,spring会通过反射来创建对象,怎么创建是它说了算,自定义的创建是不可能了。

这时候你就只能使用FactoyBean了。

这个FactoryBean当然得交给shiro实现。不过filter的创建方式自由了,我们可以通过getBean来获取这个filter,另一边的filter配置还有必要吗?

当然必要。因为这个filter怎么创建不重要,切入web的生命周期才重要,这个配置是一个规范。所以spring引入了这么一个类: DelegatingFilterProxy。就是一个代理类,自定义的实现转移到factoryBean了,这里就是公共类,主要操作是在容器中追踪并获取之前的factoryBean,并在初始化方法中获取需要的filter。

Spring容器的启动依靠监听器,而filter是在监听器之后,依靠servlet规范,在listener,filter和servlet三者之间寻找契机,并形成一个共荣圈,Spring把这种关系处理得非常妙!

Shiro切入Spring的方式的更多相关文章

  1. Spring Boot 整合 Shiro ,两种方式全总结!

    在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. 今天松哥就来和大家聊聊 Spring Boot ...

  2. Apache Shiro和Spring Security的详细对比

    参考资料: 1)Apache Shiro Apache Shiro:http://shiro.apache.org/ 在Web项目中应用 Apache Shiro:http://www.ibm.com ...

  3. Spring学习4-面向切面(AOP)之Spring接口方式

    一.初识AOP    关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节       1.AOP:Aspect ...

  4. JAVAEE——BOS物流项目11:在realm中授权、shiro的方法注解权限控制、shiro的标签权限控制、总结shiro的权限控制方式、权限管理

    1 学习计划 1.在realm中进行授权 2.使用shiro的方法注解方式权限控制 n 在spring文件中配置开启shiro注解支持 n 在Action方法上使用注解 3.★使用shiro的标签进行 ...

  5. Shiro的鉴权方式

    一. 怎么用 Shiro 支持三种方式的授权 编程式:通过写 if/else 授权代码块完成: Subject subject = SecurityUtils.getSubject(); if(sub ...

  6. apache shiro整合spring(一)

    apache shiro整合spring 将shiro配置文件整合到spring体系中 方式一:直接在spring的配置文件中import shiro的配置文件 方式二:直接在web.xml中配置sh ...

  7. 项目一:第十二天 1、常见权限控制方式 2、基于shiro提供url拦截方式验证权限 3、在realm中授权 5、总结验证权限方式(四种) 6、用户注销7、基于treegrid实现菜单展示

    1 课程计划 1. 常见权限控制方式 2. 基于shiro提供url拦截方式验证权限 3. 在realm中授权 4. 基于shiro提供注解方式验证权限 5. 总结验证权限方式(四种) 6. 用户注销 ...

  8. shiro与spring的整合

    shiro与spring的整合 上一期,我们分享了如何在项目中使用shiro,了解了shiro的基本用法,但毕竟学习shiro的目的就是在项目中应用shiro,更准确地说是在web项目中应用shiro ...

  9. 【权限管理】Apache Shiro和Spring Security的对比

    一.Shiro简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Secu ...

随机推荐

  1. Spring整合JMS(四)——事务管理(转)

    *注:别人那复制来的 Spring提供了一个JmsTransactionManager用于对JMS ConnectionFactory做事务管理.这将允许JMS应用利用Spring的事务管理特性.Jm ...

  2. CF758 D. Ability To Convert 细节处理字符串

    link 题意:给定进制数n及一串数字,问在此进制下这串数能看成最小的数(10进制)是多少(如HEX下 1|13|11 = 475) 思路:此题要仔细思考细节.首先要想使数最小那么必定有个想法是使低位 ...

  3. Shell编程——shell常用命令

    浏览器标签页的切换:Ctrl+Tab [终端]打开终端快捷建:Ctrl+Alt+t关闭终端快捷键:Ctrl+Shift+q打开新的终端标签页快捷键:Ctrl+Shift+t 关闭终端标签页快捷键:Ct ...

  4. [数据库中间件]将用户添加到DB2组授权

    1.将用户oracle添加到db2的用户组中,命令如下: usermod -a -G db2iam #将用户添加到组中并不改变当前所属组 注:以下与主题无关,只是列举一些关于用户的命令 id user ...

  5. 【BZOJ】3527: [Zjoi2014]力 FFT

    [参考]「ZJOI2014」力 - FFT by menci [算法]FFT处理卷积 [题解]将式子代入后,化为Ej=Aj-Bj. Aj=Σqi*[1/(i-j)^2],i=1~j-1. 令f(i)= ...

  6. PHP做文件限速下载

    <?php include("DBDA.class.php"); $db = new DBDA(); $bs = $_SERVER["QUERY_STRING&qu ...

  7. 支付宝Android接口4.0以上报错Failure calling remote service

    很坑爹的问题,4.0一下没问题,完全按照接口文件写的.网上一查,很多人遇到.最好直接在4.2下调试,看看报错问题,然后度娘. 将RSA文件中的加上“BC”后测试通过...NND PKCS8Encode ...

  8. javaScript 中的一些日常用法总结

    从今天开始把开发中常用到的js语法 一一记录下来 方便以后复习回顾用: 1:对字符串进行替换 replace 以及 replaceAll replace : var begin_date =begin ...

  9. 【洛谷 P1502】 窗口的星星(扫描线)

    题目链接 把每个星星作为左下角,做出长为\(w-0.5\),宽为\(h-0.5\)的矩形. \(-0.5\)是因为边框上的不算. 离散化\(y\)坐标. 记录\(2n\)个\(4\)元组\((x,y1 ...

  10. NYOJ 1272 表达式求值 第九届省赛 (字符串处理)

    title: 表达式求值 第九届省赛 nyoj 1272 tags: [栈,数据结构] 题目链接 描述 假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式. 2. 如果 X 和 Y 是 表 ...