zoukankan      html  css  js  c++  java
  • 在shiro-cas中实现 Jasig-cas的Single Sign Out 功能

    1 Single Sign Out 功能

    即单点登出功能。也就是在任意子系统进行登出操作后,其他子系统会自动登出。

    实际CAS登出的步骤为

    所以每个子系统都需要实现一个sso登出响应。

    cas-client-core包中有Single Sign Out的Session容器实现。

    具体在包 org.jasig.cas.client.session 中。

    2 实现Shiro的SSO登出功能

    1 实现CasSecurityManager

    主要目的是为了在登陆成功后保存 ST票据,并与 Shiro的sessionId进行关系映射。

    /**
     * 安全管理中心。<br>
     * 主要目的是保存session和ticket之间的关系。
     * @author Weicl
     * @since 2016.4.25
     */
    public class CasSecurityManager extends DefaultWebSecurityManager{
        
        Logger logger = LoggerFactory.getLogger(getClass());
        
        @Override
        protected void onSuccessfulLogin(AuthenticationToken token,
                AuthenticationInfo info, Subject subject) {
            
            if (token instanceof CasToken) {
                logger.info("save token info: " + token.getCredentials() + " -> " + subject.getSession(false).getId());
                SsoUtils.putTokenCache((String)token.getCredentials(), subject.getSession(false).getId());
                subject.getSession(false).setAttribute("_serviceTicket_", token.getCredentials());
            }
            
            super.onSuccessfulLogin(token, info, subject);
        }
    }
    PS: SsoUtils的putTokenCache。可以用ehcache或HashMap实现,其实没关系。

    2 实现LogoutSloFilter

    这个拦截器用来处理sso登出请求。

    /**
     * 单点登出处理
     * @author Weicl
     * @since 2016.4.25
     */
    public class LogoutSloFilter extends AdviceFilter{
        private final Logger logger = LoggerFactory.getLogger(getClass());
        private final Pattern pattern = Pattern.compile("<samlp:SessionIndex>([^<]*)</samlp:SessionIndex>");
        
        @Autowired
        private NativeSessionManager nativeSessionManager;
        
        @Override
        protected boolean preHandle(ServletRequest request, ServletResponse response)
                throws Exception {
            
            
            try {
                String logoutRequest = request.getParameter("logoutRequest");
                String serviceTicket = extractServiceTicket(logoutRequest);
                
                logger.info(" slo serviceTicket : " + serviceTicket);
                
                String sessionId = (String)SsoUtils.getTokenCache(serviceTicket);
                nativeSessionManager.stop(new DefaultSessionKey(sessionId));
                            
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            response.getWriter().write("OK");
            return false;
        }
        
        /**
         * 获取登出请求中的Ticket
         * @param logoutRequest
         * @return
         */
        private String extractServiceTicket(String logoutRequest) {
            Matcher matcher = pattern.matcher(logoutRequest);
            if (matcher.find()) {
                return matcher.group(1);
            }
            return "";
        }
    }

    3 实现TicketSessionListener

    这个类的作用是当session终止的时候,释放 SsoUtil 中的tokenCache。因为应用的session不存在了,保存这个映射关系也没有意义,而且浪费缓存空间。

    /**
     * 票据及session监听器
     * @author Weicl
     * @since 2016.4.25
     */
    public class TicketSessionListener implements SessionListener{
    
        Logger logger = LoggerFactory.getLogger(getClass());
    
        @Override
        public void onStart(Session session) {
            
        }
    
        @Override
        public void onStop(Session session) {
            logger.info("===============================");
            logger.info("stop session:" + session.getId());
            
            String ticket = (String)session.getAttribute("_serviceTicket_");
            if (ticket != null) {
                logger.info("remove serviceTicket: " + ticket);
                SsoUtils.removeTokenCache(ticket);
            }
        }
    
        @Override
        public void onExpiration(Session session) {
            onStop(session);
        }
    }

    4 配置到spring中

    一下为添加/修正的关键代码。其他shiro的配置这边就不贴出来了。

    <!-- Shiro权限过滤过滤器定义 -->
        <bean name="shiroFilterChainDefinitions" class="java.lang.String">
            <constructor-arg>
                <value>
                    /static/** = anon
                    /cas = cas
                    /login = authc
                    /logout = logout
                    /logoutSlo = logoutSlo
                    /** = user
                </value>
            </constructor-arg>
        </bean>
    
         <!-- 安全认证过滤器 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager" />
            <property name="loginUrl" value="${cas.server.url}/login?service=${cas.project.url}${adminPath}/cas" />
            <!-- 
            <property name="loginUrl" value="${adminPath}/login" /> -->
            <property name="successUrl" value="${adminPath}/login" />
            <property name="filters">
                <map>
                    <entry key="cas" value-ref="casFilter"/>
                    <entry key="authc" value-ref="formAuthenticationFilter"/>
                    <entry key="logout" value-ref="logoutFilter"></entry>
                    <entry key="logoutSlo" value-ref="logoutSloFilter"></entry>
                </map>
            </property>
            <property name="filterChainDefinitions">
                <ref bean="shiroFilterChainDefinitions"/>
            </property>
        </bean>
    
        <bean id="logoutSloFilter" class="cn.xxxxxx.base.modules.sys.security.LogoutSloFilter">
        </bean>
        
        <!-- 定义Shiro安全管理配置 -->
        <bean id="securityManager" class="cn.xxxxxx.base.common.security.shiro.session.CasSecurityManager">
            <!-- <property name="realm" ref="systemAuthorizingRealm" /> -->
            <property name="realm" ref="systemCasRealm" />
            <property name="sessionManager" ref="sessionManager" />
            <property name="cacheManager" ref="shiroCacheManager" />
        </bean>
  • 相关阅读:
    《银光志Silverlight 3.0开发详解与最佳实践》出版电子版——风云编著
    Nigel Parker 40分钟视频演示了微软的 31 项技术(附下载)
    《银光志Silverlight 3.0开发详解与最佳实践》书搞目录
    Silverlight 2使用C#遍历XML(兼容Silverlight3)
    为什么要把Silverlight归入Web 2.0?
    Silverlight明年将占据互联网设备半壁江山
    Silverlight Tools 3.0中文正式版发布(附下载地址)
    银客帝国招聘Silverlight兼职开发人员
    再说招聘:学开车一定要摸方向盘
    Expression Blend 4 下载
  • 原文地址:https://www.cnblogs.com/coprince/p/6214473.html
Copyright © 2011-2022 走看看