分享

shiro安全框架扩展教程--如何扩展实现集中式session管理

 WindySky 2018-02-09

        上一章节我和大家分享的是如何扩展异步请求分支处理,这一章节我准备分享如何实现集中式session管理,shiro一大特色就是有自己一套session机制,与原生的httpsession差不多风格的api,用起来比较顺手,我个人也比较喜欢;spring security是比较依赖与原生httpsession,所以比较难扩展这会话机制,但是我们shiro使用者就不用担心这个问题,请大家准备好鸡蛋壳,香蕉皮吧...


进入主题,我们先看看session管理器


  1. <!-- 会话管理器 -->  
  2.     <bean id="sessionManager"  
  3.         class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
  4.         <property name="sessionValidationSchedulerEnabled" value="false" />  
  5.         <property name="sessionDAO" ref="sessionDAO" />  
  6.         <property name="globalSessionTimeout" value="60000"/>  
  7.     </bean>  

基本用到就三个参数sessionValidationSchedulerEnabled(扫描session线程,负责清理超时会话), sessionDao是进行会话读写的实现,globalSessionTimeout是会话存活时间(默认是30分钟)


其他参数可看源码配置,象session的cookie编号键之类的,有需要才去改


下面看看我们的读写会话实现类


  1. public class MCSessionDAO extends AbstractSessionDAO {  
  2.   
  3.     private final static Logger log = LoggerFactory.getLogger(MCSessionDAO.class);  
  4.   
  5.     private MemcachedClient client;  
  6.   
  7.     public MCSessionDAO(MemcachedClient client) {  
  8.         if (client == null) {  
  9.             throw new RuntimeException("必须存在memcached客户端实例");  
  10.         }  
  11.         this.client = client;  
  12.     }  
  13.   
  14.     @Override  
  15.     protected Serializable doCreate(Session session) {  
  16.         Serializable sessionId = generateSessionId(session);  
  17.         assignSessionId(session, sessionId);  
  18.         try {  
  19.             client.set(sessionId.toString(), (int) session.getTimeout() / 1000, session);  
  20.         } catch (Exception e) {  
  21.             log.error(e.getMessage());  
  22.         }  
  23.         return sessionId;  
  24.     }  
  25.   
  26.     @Override  
  27.     protected Session doReadSession(Serializable sessionId) {  
  28.         Session session = null;  
  29.         try {  
  30.             session = client.get(sessionId.toString());  
  31.         } catch (Exception e) {  
  32.             log.error(e.getMessage());  
  33.         }  
  34.         return session;  
  35.     }  
  36.   
  37.     @Override  
  38.     public void delete(Session session) {  
  39.         try {  
  40.             client.delete(session.getId().toString());  
  41.         } catch (Exception e) {  
  42.             log.error(e.getMessage());  
  43.         }  
  44.     }  
  45.   
  46.     @Override  
  47.     public Collection<Session> getActiveSessions() {  
  48.         return Collections.emptySet();  
  49.     }  
  50.   
  51.     @Override  
  52.     public void update(Session session) throws UnknownSessionException {  
  53.         try {  
  54.             client.replace(session.getId().toString(), (int) session.getTimeout() / 1000, session);  
  55.         } catch (Exception e) {  
  56.             log.error(e.getMessage());  
  57.         }  
  58.     }  
  59.   
  60. }  


getActiveSessions这个方法是用来统计当前活动的session,但是memcached也没有特别好的方法能获取同一批键值对,暂时只能不支持方法,如果有朋友想到好的解决方案,望请告知下小弟



其实这个类跟普通的crud差不多,主要是通过设置memcached的过期时间来作为session的存活时间,如果返回为null则认为session是登录超时了,值得注意一个问题memcached应该需要评估足够多的初始化内存,不然可能用户量一上去,就可能有会话丢失的可能,毕竟内存不够了memcached会自动把旧的一些数据挤出去,这要看memcached的失效策略设置


很明显我们这里的sessionDao实现类已经完成,然后配置到文件里面


  1. <!-- 会话读写实现类 -->  
  2.     <bean id="sessionDAO" class="com.silvery.security.shiro.session.MCSessionDAO">  
  3.         <constructor-arg ref="memcachedClient" />  
  4.     </bean>  

如何配置memcached的客户端实例我就不啰嗦,百度一大堆,把这个sessionDAO的编号注入到我们的sessionManager管理器里面


然后我们的会话管理器又要配置到哪里呢


  1. <!-- 安全管理器 -->  
  2.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  3.         <property name="sessionManager" ref="sessionManager" />  
  4.         <property name="cacheManager" ref="shiroCacheManager" />  
  5.         <property name="realm" ref="simpleUserRealm" />  
  6.     </bean>  


然后就完工了,最后就配置个nginx+2个tomcat集群下访问测试下即可


欢迎拍砖...


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多