码迷,mamicode.com
首页 > 其他好文 > 详细

在shiro-cas中实现 Jasig-cas的Single Sign Out 功能

时间:2016-05-08 18:16:03      阅读:735      评论:0      收藏:0      [点我收藏+]

标签:

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进行关系映射。

 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实现,其实没关系。

 

2 实现LogoutSloFilter

这个拦截器用来处理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 }

3 实现TicketSessionListener

这个类的作用是当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 }

4 配置到spring中

一下为添加/修正的关键代码。其他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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!