为什么要用shiro
在介绍spring 集成shiro原理之前,我们首先应该想到的是为什么要用shiro?如果你有此问题,那与我想到一块了。简单来说,shiro是一个安全控制框架,它提供了认证、授权、会话管理、加密等功能,如果不用shiro,那么这些功能都需要自己开发,你肯定得写一个登陆过滤器/拦截器吧,肯定得写授权控制吧,肯定得写会话调度器吧等等,用了shiro就不用写这些了,shiro题你写了,并且规范了这些需求,你只需要扩展它的接口或者压根不需要扩展使用默认的,配置一下就可以实现权限控制功能。既然我们用shiro,就得弄懂它的原理。
概括
shiro是怎么在web项目中发挥的作用,原理是什么?简单来说,在web.xml中配置shiro filter,它会过滤所有请求,然后委派给内部filterchain并结合aop对annotated的方法进行权限控制。
shiroFilter原来是SpringShiroFilter
在web工程web.xml中,都会配置shiroFilter,如下
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
filter-class是DelegatingFilterProxy
,DelegatingFilterProxy
的作用,是从spring context中寻找名字为shiroFilter
的bean。
再看一下spring配置文件,是ShiroFilterFactoryBean
创建了shiroFilter
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
//省略其它无关配置
</bean>
ShiroFilterFactoryBean
是个FactoryBean,实现了FactoryBean接口,
public class ShiroFilterFactoryBean implements FactoryBean, BeanPostProcessor {
public Object getObject() throws Exception {
if (instance == null) {
instance = createInstance();
}
return instance;
}
}
那么最终是创建了什么对象呢?继续看createInstance()
方法,最终返回了SpringShiroFilter
对象
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);
}
至此,在web项目中集成shiro的大致过程就清晰了。
- web.xml中配置shiroFilter,拦截所有请求,DelegatingFilterProxy去spring配置文件中寻找shiroFilter
- spring配置文件中ShiroFilterFactoryBean 创建shiroFilter