shiro管理session

1.session

使用token登录之后可以直接使用subject获取用户session。可以操作session

[html]  view plain  copy
  1. public void test(){    
  2.         
  3.   
  4.        Factory<org.apache.shiro.mgt.SecurityManager> factory =  new IniSecurityManagerFactory("classpath:shiro.ini");      
  5.        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();    
  6.        SecurityUtils.setSecurityManager(securityManager);    
  7.        Subject subject = SecurityUtils.getSubject();          
  8.        UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");//这个用户在ini文件中存在,shiro自动做密码和用户名匹配验证    
  9.        //登录  
  10.        subject.login(token);      
  11.        //获取用户session(如果当前用户没有常见session的话,true则创建一个并返回,false为返回null)  
  12.        Session session = subject.getSession(true);  
  13.          
  14.        //主机  
  15.        System.out.println("host:"+session.getHost());  
  16.        //session超时时间  
  17.        session.setTimeout(1500000);  
  18.        System.out.println("timeout:"+session.getTimeout());  
  19.        //属性参数值  
  20.        session.setAttribute("name", subject.getPrincipal());  
  21.        System.out.println("name:"+session.getAttribute("name"));  
  22.        session.removeAttribute("name");  
  23.        System.out.println("attributekeys:"+session.getAttributeKeys());  
  24.        //id  
  25.        System.out.println("id:"+session.getId());  
  26.        //访问时间(创建session的时间和最后访问session的时间)  
  27.        System.out.println("lastAccessTime:"+session.getLastAccessTime());  
  28.        session.touch();//更新会话访问时间    
  29.        System.out.println("StartTimestamp:"+session.getStartTimestamp());  
  30.        //销毁session  
  31.        session.stop();   
  32.   
  33.    }    


2.session管理器

session管理器用来管理所有用户的subject的session。包括创建、维护、删除、失效、验证。

Shiro提供了三个默认实现:

(1)DefaultSessionManager:DefaultSecurityManager使用的默认实现,用于JavaSE环境;

[html]  view plain  copy
  1. [main]    
  2. sessionManager=org.apache.shiro.session.mgt.DefaultSessionManager    
  3. securityManager.sessionManager=$sessionManager   

(2)ServletContainerSessionManager:DefaultWebSecurityManager使用的默认实现,用于Web环境,其直接使用Servlet容器的会话;

shiro.ini:

[html]  view plain  copy
  1. [main]  
  2. sessionManager=org.apache.shiro.web.session.mgt.ServletContainerSessionManager   
  3. securityManager.sessionManager=$sessionManager   
  4. #设置全局session过期时间,默认30分钟  
  5. sessionManager. globalSessionTimeout=1800000  
  6. [users] zhang=123 wang=123   

这个session管理器使用了servlet,所以可以在web.xml文件中设置session超时时间

web.xml:

[html]  view plain  copy
  1. <session-config>    
  2.   <session-timeout>30</session-timeout>    
  3. </session-config>   
超时时间由shiro设置,这里设置的是全部session的过期时间,session各自的过期时间可以代码设置session单独的过期时间


(3)DefaultWebSessionManager:用于Web环境的实现,可以替代ServletContainerSessionManager,自己维护着会话,直接废弃了Servlet容器的会话管理。

shiro.ini:

[html]  view plain  copy
  1. [main]  
  2.   
  3. #sessionManager创建会话Cookie的模板  
  4. sessionIdCookie=org.apache.shiro.web.servlet.SimpleCookie    
  5.   
  6. #session管理器  
  7. sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager  
  8.    
  9. #设置Cookie名字,默认为JSESSIONID   
  10. sessionIdCookie.name=sid    
  11.   
  12. #设置Cookie的域名,默认空,即当前访问的域名  
  13. #sessionIdCookie.domain=sishuok.com   
  14. #设置Cookie的路径,默认空,即存储在域名根下   
  15. #sessionIdCookie.path=  
  16.     
  17. #设置Cookie的过期时间,秒为单位,默认-1表示关闭浏览器时过期  
  18. sessionIdCookie.maxAge=1800  
  19.   
  20. #如果设置为true,则客户端不会暴露给客户端脚本代码  
  21. #使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击  
  22. #此特性需要实现了Servlet 2.5 MR6及以上版本的规范的Servlet    
  23. sessionIdCookie.httpOnly=true    
  24.   
  25. #是否启用/禁用Session Id Cookie,默认是启用的,  
  26. #如果禁用后将不会设置Session Id Cookie  
  27. #即默认使用了Servlet容器的JSESSIONID  
  28. #且通过URL重写(URL中的“;JSESSIONID=id”部分)保存Session Id  
  29. sessionManager.sessionIdCookieEnabled=true  
  30.     
  31. sessionManager.sessionIdCookie=$sessionIdCookie   
  32. securityManager.sessionManager=$sessionManager   
  33.   
  34. [users]    
  35. zhang=123    
  36. wang=123  


3.session监听器

session监听器需要在配置文件中指定实现类
shiro.ini:
[html]  view plain  copy
  1. [main]  
  2. sessionListener=com.tyf.www.MySessionListener   
  3. sessionManager.sessionListeners=$sessionListener  
  4.   
  5.   
  6. [users]    
  7. zhang=123    
  8. wang=123    


(1)监听会话创建、过期、停止

[html]  view plain  copy
  1. public class MySessionListener implements SessionListener {    
  2.     @Override    
  3.     public void onStart(Session session) {//会话创建时触发    
  4.         System.out.println("会话创建:" + session.getId());    
  5.     }    
  6.     @Override    
  7.     public void onExpiration(Session session) {//会话过期时触发    
  8.         System.out.println("会话过期:" + session.getId());    
  9.     }    
  10.     @Override    
  11.     public void onStop(Session session) {//退出/会话过期时触发    
  12.         System.out.println("会话停止:" + session.getId());    
  13.     }      
  14. }    

(2)监听会话的某个事件

[html]  view plain  copy
  1. public class MySessionListener extends SessionListenerAdapter {    
  2.     @Override    
  3.     public void onStart(Session session) {    
  4.         System.out.println("会话创建:" + session.getId());    
  5.     }    
  6. }    

4.session持久化

encache依赖

[html]  view plain  copy
  1. <!-- encache -->   
  2. <dependency>  
  3.    <groupId>org.apache.shiro</groupId>  
  4.    <artifactId>shiro-ehcache</artifactId>  
  5.    <version>1.2.3</version>  
  6. </dependency>  

shiro封装了sessionDao用于对sesson的增删改查,并且采用ehcache缓存作为存储方式(ehcache+terracotta可以实现session容器无关的存储集群)

shiro.ini

[html]  view plain  copy
  1. [main]  
  2.   
  3. #设置sessionDao实现类  
  4. sessionDAO=org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO   
  5.   
  6. #设置Session缓存名字,默认就是shiro-activeSessionCache   
  7. sessionDAO.activeSessionsCacheName=shiro-activeSessionCache   
  8.    
  9. #缓存管理器,用于管理缓存的,此处使用Ehcache实现  
  10. cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager  
  11.   
  12. #设置ehcache缓存的配置文件    
  13. cacheManager.cacheManagerConfigFile=classpath:ehcache.xml    
  14.   
  15. sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager    
  16. sessionManager.sessionDAO=$sessionDAOsecurityManager.cacheManager = $cacheManager  
  17. [users] zhang=123 wang=123   


 
 同时可以设置sessionid生成方式: 
 

[html]  view plain  copy
  1. sessionIdGenerator=org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator    
  2. sessionDAO.sessionIdGenerator=$sessionIdGenerator    


ehcache.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <ehcache name="es">  
  3.   
  4.     <diskStore path="java.io.tmpdir"/>  
  5.   
  6.     <cache name="shiro-activeSessionCache"  
  7.            maxEntriesLocalHeap="10000"  
  8.            overflowToDisk="false"  
  9.            eternal="false"  
  10.            diskPersistent="false"  
  11.            timeToLiveSeconds="0"  
  12.            timeToIdleSeconds="0"  
  13.            statistics="true"/>  
  14.   
  15. </ehcache>  


(4)自定义sessionDao

自己实现一个sessdao将session序列化进mysql,在通过获取session时会先到ehcahce中查找之后再到mysql中查找

依赖


创建session持久化数据库

[html]  view plain  copy
  1. drop table if exists sessions;  
  2.   
  3. create table sessions (  
  4.   id varchar(200),  
  5.   session varchar(2000),  
  6.   constraint pk_sessions primary key(id)  
  7. charset=utf8 ENGINE=InnoDB;  

序列化工具类

[html]  view plain  copy
  1. import org.apache.shiro.codec.Base64;  
  2. import org.apache.shiro.session.Session;  
  3.   
  4. import java.io.ByteArrayInputStream;  
  5. import java.io.ByteArrayOutputStream;  
  6. import java.io.ObjectInputStream;  
  7. import java.io.ObjectOutputStream;  
  8.   
  9. /*  
  10.  *   
  11.  *      session序列化工具类  
  12.  *   
  13.  *   
  14.  */  
  15. public class SerializableUtils {  
  16.   
  17.     //序列化  
  18.     public static String serialize(Session session) {  
  19.         try {  
  20.             ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  21.             ObjectOutputStream oos = new ObjectOutputStream(bos);  
  22.             oos.writeObject(session);  
  23.             return Base64.encodeToString(bos.toByteArray());  
  24.         } catch (Exception e) {  
  25.             throw new RuntimeException("serialize session error", e);  
  26.         }  
  27.     }  
  28.       
  29.     //反序列化  
  30.     public static Session deserialize(String sessionStr) {  
  31.         try {  
  32.             ByteArrayInputStream bis = new ByteArrayInputStream(Base64.decode(sessionStr));  
  33.             ObjectInputStream ois = new ObjectInputStream(bis);  
  34.             return (Session)ois.readObject();  
  35.         } catch (Exception e) {  
  36.             throw new RuntimeException("deserialize session error", e);  
  37.         }  
  38.     }  
  39. }  

jdbc工具类

[html]  view plain  copy
  1. import com.alibaba.druid.pool.DruidDataSource;  
  2. import org.springframework.jdbc.core.JdbcTemplate;  
  3.   
  4.   
  5. /*  
  6.  *        
  7.  *  jdbc工具类  
  8.  *   
  9.  *   
  10.  */  
  11. public class JdbcTemplateUtils {  
  12.   
  13.     private static JdbcTemplate jdbcTemplate;  
  14.   
  15.     public static JdbcTemplate jdbcTemplate() {  
  16.         if(jdbcTemplate == null) {  
  17.             jdbcTemplate = createJdbcTemplate();  
  18.         }  
  19.         return jdbcTemplate;  
  20.     }  
  21.   
  22.     private static JdbcTemplate createJdbcTemplate() {  
  23.   
  24.         DruidDataSource ds = new DruidDataSource();  
  25.         ds.setDriverClassName("com.mysql.jdbc.Driver");  
  26.         ds.setUrl("jdbc:mysql://localhost:3306/shiro");  
  27.         ds.setUsername("root");  
  28.         ds.setPassword("1234");  
  29.   
  30.         return new JdbcTemplate(ds);  
  31.     }  
  32.   
  33. }  

sessionDao

[html]  view plain  copy
  1. import org.apache.shiro.session.Session;  
  2. import org.apache.shiro.session.mgt.ValidatingSession;  
  3. import org.apache.shiro.session.mgt.eis.CachingSessionDAO;  
  4. import org.springframework.jdbc.core.JdbcTemplate;  
  5. import java.io.Serializable;  
  6. import java.util.List;  
  7.   
  8.   
  9. /*  
  10.  *      sessionDao:继承了CachingSessionDao意味着会先查找缓存,再通过下面的方法查找数据库  
  11.  *   
  12.  *   
  13.  */  
  14. public class MySessionDAO extends CachingSessionDAO {  
  15.   
  16.     private JdbcTemplate jdbcTemplate = JdbcTemplateUtils.jdbcTemplate();  
  17.   
  18.     //在创建完session之后会调用  
  19.     @Override  
  20.     protected Serializable doCreate(Session session) {  
  21.         System.out.println("doCreate");  
  22.         Serializable sessionId = generateSessionId(session);  
  23.         assignSessionId(session, sessionId);  
  24.         String sql = "insert into sessions(id, session) values(?,?)";  
  25.         jdbcTemplate.update(sql, sessionId, SerializableUtils.serialize(session));  
  26.         return session.getId();  
  27.     }  
  28.     //更新session最后访问时间、停止session、设置超时时间、移除属性值时会调用  
  29.     @Override  
  30.     protected void doUpdate(Session session) {  
  31.         System.out.println("doUpdate");  
  32.         if(session instanceof ValidatingSession && !((ValidatingSession)session).isValid()) {  
  33.             return; //如果会话过期/停止 没必要再更新了  
  34.         }  
  35.         String sql = "update sessions set session=? where id=?";  
  36.         jdbcTemplate.update(sql, SerializableUtils.serialize(session), session.getId());  
  37.     }  
  38.     //用户logout、session过期会调用  
  39.     @Override  
  40.     protected void doDelete(Session session) {  
  41.         System.out.println("doDelete");  
  42.         String sql = "delete from sessions where id=?";  
  43.         jdbcTemplate.update(sql, session.getId());  
  44.     }  
  45.     @Override  
  46.     protected Session doReadSession(Serializable sessionId) {  
  47.         String sql = "select session from sessions where id=?";  
  48.         List<String> sessionStrList = jdbcTemplate.queryForList(sql, String.class, sessionId);  
  49.         if(sessionStrList.size() == 0) return null;  
  50.         return SerializableUtils.deserialize(sessionStrList.get(0));  
  51.     }  
  52. }  

shiro.ini

[html]  view plain  copy
  1. [main]  
  2.   
  3. #设置sessionDao实现类  
  4. sessionDAO=com.tyf.www.MySessionDAO  
  5.   
  6. #设置Session缓存名字,默认就是shiro-activeSessionCache   
  7. sessionDAO.activeSessionsCacheName=shiro-activeSessionCache   
  8.    
  9.   
  10.   
  11. #缓存管理器,用于管理缓存的,此处使用Ehcache实现  
  12. cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager  
  13.   
  14. #设置ehcache缓存的配置文件    
  15. cacheManager.cacheManagerConfigFile=classpath:ehcache.xml    
  16.     
  17. sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager  
  18. sessionManager.sessionDAO=$sessionDAO  
  19. securityManager.cacheManager = $cacheManager  
  20. securityManager.sessionManager=$sessionManager  
  21.   
  22. [users]    
  23. zhang=123    
  24. wang=123    

ehcache.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <ehcache name="es">  
  3.   
  4.     <diskStore path="java.io.tmpdir"/>  
  5.   
  6.     <cache name="shiro-activeSessionCache"  
  7.            maxEntriesLocalHeap="10000"  
  8.            overflowToDisk="false"  
  9.            eternal="false"  
  10.            diskPersistent="false"  
  11.            timeToLiveSeconds="0"  
  12.            timeToIdleSeconds="0"  
  13.            statistics="true"/>  
  14.   
  15. </ehcache>  


web.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <web-app   
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"    
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"    
  6.     id="WebApp_ID" version="3.0">  
  7.   <display-name>Archetype Created Web Application</display-name>  
  8.     
  9.     
  10.     <!--- EnvironmentLoaderListener用来生成SecurityManager -->  
  11.     <listener>  
  12.         <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>  
  13.     </listener>  
  14.     <context-param>  
  15.         <param-name>shiroEnvironmentClass</param-name>  
  16.         <param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value><!-- 默认先从/WEB-INF/shiro.ini,如果没有找classpath:shiro.ini -->  
  17.     </context-param>  
  18.     <context-param>  
  19.         <param-name>shiroConfigLocations</param-name>  
  20.         <param-value>classpath:shiro.ini</param-value><!-- 指定shiro配置文件路径 -->  
  21.     </context-param>  
  22.     <filter>  
  23.         <filter-name>shiroFilter</filter-name>  
  24.         <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>  
  25.     </filter>  
  26.     <filter-mapping>  
  27.         <filter-name>shiroFilter</filter-name>  
  28.         <url-pattern>/*</url-pattern>  
  29.     </filter-mapping>  
  30.       
  31.     
  32. </web-app>  

测试类

[html]  view plain  copy
  1. public void test(){    
  2.         
  3.   
  4.        Factory<org.apache.shiro.mgt.SecurityManager> factory =  new IniSecurityManagerFactory("classpath:shiro.ini");      
  5.        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();    
  6.        SecurityUtils.setSecurityManager(securityManager);    
  7.        Subject subject = SecurityUtils.getSubject();          
  8.        UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");//这个用户在ini文件中存在,shiro自动做密码和用户名匹配验证    
  9.          
  10.        //登录  
  11.        subject.login(token);   
  12.          
  13.        //获取用户session  
  14.        Session session = subject.getSession(true);  
  15.        System.out.println("id:"+session.getId());  
  16.          
  17.        //用户退出(还没有删除session)  
  18.        subject.logout();  
  19.          
  20.        //销毁session  
  21.        session.stop();  
  22.          
  23.          
  24.    }    


分别创建session、打印sessioni_d、销毁session。查看数据库中session记录:


5.session验证

web环境中用户不主动退出,shiro不知道session是否已经过期,所以shiro提供一个验证器来定期验证session是否过期

[html]  view plain  copy
  1. sessionValidationScheduler=org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler    
  2. sessionValidationScheduler.interval = 3600000    
  3. sessionValidationScheduler.sessionManager=$sessionManager    
  4. sessionManager.globalSessionTimeout=1800000    
  5. sessionManager.sessionValidationSchedulerEnabled=true    
  6. sessionManager.sessionValidationScheduler=$sessionValidationScheduler    

sessionValidationScheduler:会话验证调度器,sessionManager默认就是使用ExecutorServiceSessionValidationScheduler,其使用JDK的ScheduledExecutorService进行定期调度并验证会话是否过期;
sessionValidationScheduler.interval:设置调度时间间隔,单位毫秒,默认就是1小时;
sessionValidationScheduler.sessionManager:设置会话验证调度器进行会话验证时的会话管理器;
sessionManager.globalSessionTimeout:设置全局会话超时时间,默认30分钟,即如果30分钟内没有访问会话将过期;
sessionManager.sessionValidationSchedulerEnabled:是否开启会话验证器,默认是开启的;
sessionManager.sessionValidationScheduler:设置会话验证调度器,默认就是使用ExecutorServiceSessionValidationScheduler。


6.sessionFactory

sessionFactory是创建会话的工厂,根据相应的Subject上下文信息来创建会话;默认提供了SimpleSessionFactory用来创建SimpleSession会话


自定义session

[html]  view plain  copy
  1. public class OnlineSession extends SimpleSession {    
  2.     public static enum OnlineStatus {    
  3.         on_line("在线"), hidden("隐身"), force_logout("强制退出");    
  4.         private final String info;    
  5.         private OnlineStatus(String info) {    
  6.             this.info = info;    
  7.         }    
  8.         public String getInfo() {    
  9.             return info;    
  10.         }    
  11.     }    
  12.     private String userAgent; //用户浏览器类型    
  13.     private OnlineStatus status = OnlineStatus.on_line; //在线状态    
  14.     private String systemHost; //用户登录时系统IP    
  15.     //省略其他    
  16. }     

自定义sessionFactory

[html]  view plain  copy
  1. public class OnlineSessionFactory implements SessionFactory {    
  2.     
  3.     @Override    
  4.     public Session createSession(SessionContext initData) {    
  5.         OnlineSession session = new OnlineSession();    
  6.         if (initData != null && initData instanceof WebSessionContext) {    
  7.             WebSessionContext sessionContext = (WebSessionContext) initData;    
  8.             HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();    
  9.             if (request != null) {    
  10.                 session.setHost(IpUtils.getIpAddr(request));    
  11.                 session.setUserAgent(request.getHeader("User-Agent"));    
  12.                 session.setSystemHost(request.getLocalAddr() + ":" + request.getLocalPort());    
  13.             }    
  14.         }    
  15.         return session;    
  16.     }    
  17. }  

shiro.ini

[html]  view plain  copy
  1. sessionFactory=org.apache.shiro.session.mgt.OnlineSessionFactory    
  2. sessionManager.sessionFactory=$sessionFactory  

转载地址:https://blog.csdn.net/qq_34448345/article/details/78948235

猜你喜欢

转载自blog.csdn.net/m0_38053538/article/details/80431240