Spring Shiro处理过程

Shiro中的Filters定义

下图为Shiro中所有的Filter定义
Shiro中的Filter定义
可以看出,基本上分为两大类的Filter,一个是PathMatchingFilter,另一个就是LogoutFilterLogoutFilter作为登出Filter,暂不介绍。
所有的filter,全部是OncePerRequestFilter的子类,OncePerRequestFilter作为Filter中doFilter实现的主要类,主要内容在其子类的doFilterInternal中实现。
首先,需要知道Shiro的启动过程和加载顺序,当前以Spring+Shiro+CAS进行配置。

1. web.xml配置

    <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>

使用spring进行托管Shiro Filter

2 Shiro配置

    <!-- 配置CAS Filter,用于CAS校验用户是否登录与用户权限 -->
    <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
        <property name="failureUrl" value="/shiro/error"/>
    </bean>

    <!-- Shiro Filter -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl"
                  value="https://cas_server_url/cas/login?service=http://localhost:8080/cas"/>
        <property name="filters">
            <map>
                <entry key="casFilter" value-ref="casFilter"/>
                <entry key="role" value-ref="roleFilter"/>
            </map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                <!-- 用于控制用户登录验证 -->
                /cas = casFilter
                <!-- 用于控制用户权限验证 -->
                /** = role
            </value>
        </property>
    </bean>

    <bean id="roleRealm" class="org.ihsxin.test.shiro.core.realm.RoleRealm">
        <property name="casServerUrlPrefix" value="https://cas_server_url/cas/"/>
        <property name="casService" value="http://localhost:8080/cas"/>
        <property name="roleManager">
            <bean class="org.ihsxin.test.shiro.core.role.impl.RoleManagerImpl">
                <property name="userRoleMapper" ref="userRoleMapper"/>
            </bean>
        </property>
    </bean>

    <bean id="memoryConstrainedCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/>
    <bean id="memorySessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"/>

    <bean id="defaultSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="cacheManager" ref="memoryConstrainedCacheManager"/>
        <property name="sessionDAO" ref="memorySessionDAO"/>
    </bean>

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="roleRealm"/>
        <property name="subjectFactory" ref="casSubjectFactory"/>
        <property name="cacheManager" ref="memoryConstrainedCacheManager"/>
        <property name="sessionManager" ref="defaultSessionManager"/>
    </bean>

    <bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory"/>

    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
        <property name="arguments" ref="securityManager"/>
    </bean>

首先,需要明白Shiro框架的几大概念:
1.1 SecurityManager

1.2 Subject

1.3 Realm

现在,以执行顺序方式,追踪记录一层请求的代码路由顺序。

1. Spring Shiro

PathMatchingFilter作为大的父类,主要的一个功能,就是匹配操作符及操作路径,如果符合这个路径,才执行自身方法。

    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
// 如果当前的适用的Path没有,默认允许,直接返回true
        if (this.appliedPaths == null || this.appliedPaths.isEmpty()) {
            if (log.isTraceEnabled()) {
                log.trace("appliedPaths property is null or empty.  This Filter will passthrough immediately.");
            }
            return true;
        }
        // 遍历自身的Apply path,如果匹配,则通过执行isFilterChainContinued方法
        for (String path : this.appliedPaths.keySet()) {
            // If the path does match, then pass on to the subclass implementation for specific checks
            //(first match 'wins'):
            if (pathsMatch(path, request)) {
                log.trace("Current requestURI matches pattern '{}'.  Determining filter chain execution...", path);
                Object config = this.appliedPaths.get(path);
                return isFilterChainContinued(request, response, path, config);
            }
        }

        //no path matched, allow the request to go through:
        return true;
    }
 /**
     * Simple method to abstract out logic from the preHandle implementation - it was getting a bit unruly.
     *
     * @since 1.2
     */
    @SuppressWarnings({"JavaDoc"})
    private boolean isFilterChainContinued(ServletRequest request, ServletResponse response,
                                           String path, Object pathConfig) throws Exception {

        if (isEnabled(request, response, path, pathConfig)) { //isEnabled check added in 1.2
            if (log.isTraceEnabled()) {
                log.trace("Filter '{}' is enabled for the current request under path '{}' with config [{}].  " +
                        "Delegating to subclass implementation for 'onPreHandle' check.",
                        new Object[]{getName(), path, pathConfig});
            }
            //The filter is enabled for this specific request, so delegate to subclass implementations
            //so they can decide if the request should continue through the chain or not:
            // 做一些子类的操作
            return onPreHandle(request, response, pathConfig);
        }

        if (log.isTraceEnabled()) {
            log.trace("Filter '{}' is disabled for the current request under path '{}' with config [{}].  " +
                    "The next element in the FilterChain will be called immediately.",
                    new Object[]{getName(), path, pathConfig});
        }
        //This filter is disabled for this specific request,
        //return 'true' immediately to indicate that the filter will not process the request
        //and let the request/response to continue through the filter chain:
        return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值