标签:
即单点登出功能。也就是在任意子系统进行登出操作后,其他子系统会自动登出。
实际CAS登出的步骤为
所以每个子系统都需要实现一个sso登出响应。
cas-client-core包中有Single Sign Out的Session容器实现。
具体在包 org.jasig.cas.client.session 中。
主要目的是为了在登陆成功后保存 ST票据,并与 Shiro的sessionId进行关系映射。
1 /** 2 * 安全管理中心。<br> 3 * 主要目的是保存session和ticket之间的关系。 4 * @author Weicl 5 * @since 2016.4.25 6 */ 7 public class CasSecurityManager extends DefaultWebSecurityManager{ 8 9 Logger logger = LoggerFactory.getLogger(getClass()); 10 11 @Override 12 protected void onSuccessfulLogin(AuthenticationToken token, 13 AuthenticationInfo info, Subject subject) { 14 15 if (token instanceof CasToken) { 16 logger.info("save token info: " + token.getCredentials() + " -> " + subject.getSession(false).getId()); 17 SsoUtils.putTokenCache((String)token.getCredentials(), subject.getSession(false).getId()); 18 subject.getSession(false).setAttribute("_serviceTicket_", token.getCredentials()); 19 } 20 21 super.onSuccessfulLogin(token, info, subject); 22 } 23 }
PS: SsoUtils的putTokenCache。可以用ehcache或HashMap实现,其实没关系。
这个拦截器用来处理sso登出请求。
1 /** 2 * 单点登出处理 3 * @author Weicl 4 * @since 2016.4.25 5 */ 6 public class LogoutSloFilter extends AdviceFilter{ 7 private final Logger logger = LoggerFactory.getLogger(getClass()); 8 private final Pattern pattern = Pattern.compile("<samlp:SessionIndex>([^<]*)</samlp:SessionIndex>"); 9 10 @Autowired 11 private NativeSessionManager nativeSessionManager; 12 13 @Override 14 protected boolean preHandle(ServletRequest request, ServletResponse response) 15 throws Exception { 16 17 18 try { 19 String logoutRequest = request.getParameter("logoutRequest"); 20 String serviceTicket = extractServiceTicket(logoutRequest); 21 22 logger.info(" slo serviceTicket : " + serviceTicket); 23 24 String sessionId = (String)SsoUtils.getTokenCache(serviceTicket); 25 nativeSessionManager.stop(new DefaultSessionKey(sessionId)); 26 27 } catch (Exception e) { 28 e.printStackTrace(); 29 } 30 31 response.getWriter().write("OK"); 32 return false; 33 } 34 35 /** 36 * 获取登出请求中的Ticket 37 * @param logoutRequest 38 * @return 39 */ 40 private String extractServiceTicket(String logoutRequest) { 41 Matcher matcher = pattern.matcher(logoutRequest); 42 if (matcher.find()) { 43 return matcher.group(1); 44 } 45 return ""; 46 } 47 }
这个类的作用是当session终止的时候,释放 SsoUtil 中的tokenCache。因为应用的session不存在了,保存这个映射关系也没有意义,而且浪费缓存空间。
1 /** 2 * 票据及session监听器 3 * @author Weicl 4 * @since 2016.4.25 5 */ 6 public class TicketSessionListener implements SessionListener{ 7 8 Logger logger = LoggerFactory.getLogger(getClass()); 9 10 @Override 11 public void onStart(Session session) { 12 13 } 14 15 @Override 16 public void onStop(Session session) { 17 logger.info("==============================="); 18 logger.info("stop session:" + session.getId()); 19 20 String ticket = (String)session.getAttribute("_serviceTicket_"); 21 if (ticket != null) { 22 logger.info("remove serviceTicket: " + ticket); 23 SsoUtils.removeTokenCache(ticket); 24 } 25 } 26 27 @Override 28 public void onExpiration(Session session) { 29 onStop(session); 30 } 31 }
一下为添加/修正的关键代码。其他shiro的配置这边就不贴出来了。
1 <!-- Shiro权限过滤过滤器定义 --> 2 <bean name="shiroFilterChainDefinitions" class="java.lang.String"> 3 <constructor-arg> 4 <value> 5 /static/** = anon 6 /cas = cas 7 /login = authc 8 /logout = logout 9 /logoutSlo = logoutSlo 10 /** = user 11 </value> 12 </constructor-arg> 13 </bean> 14 15 <!-- 安全认证过滤器 --> 16 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> 17 <property name="securityManager" ref="securityManager" /> 18 <property name="loginUrl" value="${cas.server.url}/login?service=${cas.project.url}${adminPath}/cas" /> 19 <!-- 20 <property name="loginUrl" value="${adminPath}/login" /> --> 21 <property name="successUrl" value="${adminPath}/login" /> 22 <property name="filters"> 23 <map> 24 <entry key="cas" value-ref="casFilter"/> 25 <entry key="authc" value-ref="formAuthenticationFilter"/> 26 <entry key="logout" value-ref="logoutFilter"></entry> 27 <entry key="logoutSlo" value-ref="logoutSloFilter"></entry> 28 </map> 29 </property> 30 <property name="filterChainDefinitions"> 31 <ref bean="shiroFilterChainDefinitions"/> 32 </property> 33 </bean> 34 35 <bean id="logoutSloFilter" class="cn.xxxxxx.base.modules.sys.security.LogoutSloFilter"> 36 </bean> 37 38 <!-- 定义Shiro安全管理配置 --> 39 <bean id="securityManager" class="cn.xxxxxx.base.common.security.shiro.session.CasSecurityManager"> 40 <!-- <property name="realm" ref="systemAuthorizingRealm" /> --> 41 <property name="realm" ref="systemCasRealm" /> 42 <property name="sessionManager" ref="sessionManager" /> 43 <property name="cacheManager" ref="shiroCacheManager" /> 44 </bean>
在shiro-cas中实现 Jasig-cas的Single Sign Out 功能
标签:
原文地址:http://www.cnblogs.com/damaeryi/p/5470883.html