1. 程式人生 > >shiro登入流程

shiro登入流程

ShiroFilter

Shiro提供了與Web整合的支援,其通過一個ShiroFilter入口來攔截需要安全控制的URL,然後進行相應的控制,ShiroFilter類似於如Strut2/SpringMVC這種web框架的前端
其是安全控制的入口點,其負責讀取配置(如ini配置檔案),然後判斷URL是否需要登入/許可權等工作。

web.xml配置名字為shiroFilter的過濾器,這個bean去 shiro.in 或者shiro.xml配置檔案中找

首先是在web.xml中配置DelegatingFilterProxy

    <!-- Shiro Security filter -->
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <async-supported>true</async-supported> </filter> <filter-mapping> <filter-name
>
shiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>

配置好DelegatingFilterProxy後,下面只要再把ShiroFilter配置到Spring容器(此處為Spring的配置檔案)即可:
(使用ShiroFilterFactoryBean建立shiroFilter)

 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" />
        <property name="loginUrl" value="/login" />
        <property name="successUrl" value="/" />
        <property name="filterChainDefinitions">
            <value>
                /favicon.ico = anon
                /assets/** = anon
                /jd/** = anon
                /uf/** = anon
                /upload/** = anon
                /upload-file = anon
                /api/code = anon
                /services/** = anon
                /api/login = anon
                /pushCall = anon
                /oc/** = anon
                /fl/** = anon
                /login = authc
                /logout = logout
                /api/v2/oc/user/login=anon
                /api/v2/oc/user/register=anon
                /api/v2/oc/user/checkPhoneCode=anon
                /api/v2/oc/user/reset/code=anon
                /api/v2/oc/user/reset/password=anon
                /api/v1/eam/**=mobile
                /api/v2/**=mobile
                /api/** = anon
                /** = user
            </value>
        </property>
         <!--  做攔截過濾  -->
        <property name="filters">
            <map>
                <entry key="mobile">
                    <bean class="com.xx.xx.shiro.filter.MobileAuthenticatingFilter"></bean>
                </entry>
            </map>
        </property>

    </bean>

使用了ShiroFilterFactoryBean來建立shiroFilter,這裡用到了Spring中一種特殊的Bean——FactoryBean。當需要得到名為”shiroFilter“的bean時,會呼叫其getObject()來獲取例項。下面我們通過分析ShiroFilterFactoryBean建立例項的過程來探究Shiro是如何實現安全攔截的:

ShiroFilterFactoryBean建立shiroFilter

public Object getObject() throws Exception { 
    if (instance == null) { 
        instance = createInstance(); 
    }
 return instance; 
 }

其中呼叫了createInstance()來建立例項:


    protected AbstractShiroFilter createInstance() throws Exception { 
        // 這裡是通過FactoryBean注入的SecurityManager(必須)
        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(); 
        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
        chainResolver.setFilterChainManager(manager);
        return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
    }

可以看到建立SpringShiroFilter時用到了兩個元件:SecurityManager和ChainResolver。

先有一個大體的瞭解,那麼對於原始碼分析會有不少幫助。下面會對以上兩個重要的元件進行分析,包括PathMatchingFilterChainResolver和FilterChainManager。首先貼一段ShiroFilter的在配置檔案中的定義:

========> ="filterChainDefinitions">
 <value> /resources/** = anon 
/download/** = anon 
/special/unauthorized = anon
 /register = anon
/logout = logout 
/admin/** = roles[admin] 
/** = user >

PathMatchingFilterChainResolver和FilterChainManager的建立過程:

protected FilterChainManager createFilterChainManager() { 
 //預設使用的FilterChainManager是DefaultFilterChainManager
 DefaultFilterChainManager manager = new DefaultFilterChainManager(); 
// 將ShiroFilterFactoryBean配置的一些公共屬性(上面配置的loginUrl,successUrl,unauthorizeUrl)應用到預設註冊的filter上去 
for (Filter filter : defaultFilters.values()) { applyGlobalPropertiesIfNecessary(filter); 
} 
Filter filters = getFilters(); 
if (!CollectionUtils.isEmpty(filters)) {
 for (, Filter> entry : filters.entrySet()) { 
 Filter filter = entry.getValue(); applyGlobalPropertiesIfNecessary(filter);
  if (filter instanceof Nameable) {
} 
//將Filter新增到manager中去,可以看到對於Filter的管理是依賴於FilterChainManager的                         manager.addFilter(name, filter, false); 
} 
} 
 String> chains = getFilterChainDefinitionMap();
 for (String> entry : chains.entrySet()) { 
 String chainDefinition = entry.getValue();
manager.createChain(url, chainDefinition); } } 
return manager; }

待完成—-