• 超级简单学习Shiro会话管理


    目录

    一、会话管理

    二、缓存管理


    一、会话管理

    ①为什么要用Shiro会话?

    Shiro的会话管理具备Tomcat的会话管理的一切功能
    相较于Tomcat的session,shiro提供了对于分布式session的管理

    ②为啥要使用分布式的session管理呢?

     当我们在使用一个项目时是多个的数据访问量的,所以肯定会配置多个Tomcat服务器进行交互,但是我们无法确定我们每次请求的都是同一个Tomcat,也就没办法保证我们的session存值能够正确拿到。

    所以我们采用Shiro会话来存值原本存放在Tomcat上面的值(图示)

    ③实现步骤:

    1)自定义session监听器

    1. package com.zq.ssm.shiro;
    2. import org.apache.shiro.session.Session;
    3. import org.apache.shiro.session.SessionListener;
    4. public class MysessionListener implements SessionListener {
    5. @Override
    6. public void onStart(Session session) {
    7. System.out.println("ShiroSessionListener.onStart..."+session.getId());
    8. }
    9. @Override
    10. public void onStop(Session session) {
    11. System.out.println("ShiroSessionListener.onStop..."+session.getId());
    12. }
    13. @Override
    14. public void onExpiration(Session session) {
    15. System.out.println("ShiroSessionListener.onExpiration..."+session.getId());
    16. }
    17. }

    2)添加application-shiro的配置 

    1. <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    2. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    3. <property name="realm" ref="shiroRealm" />
    4. <property name="sessionManager" ref="sessionManager">property>
    5. bean>
    6. <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator">
    7. bean>
    8. <bean id="customSessionDao" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO">
    9. <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
    10. bean>
    11. <bean id="shiroSessionListener" class="com.zq.ssm.shiro.MysessionListener"/>
    12. <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    13. <constructor-arg value="shiro.session"/>
    14. <property name="maxAge" value="-1"/>
    15. <property name="httpOnly" value="true"/>
    16. bean>
    17. <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    18. <property name="globalSessionTimeout" value="120000"/>
    19. <property name="sessionDAO" ref="customSessionDao"/>
    20. <property name="sessionValidationInterval" value="60000"/>
    21. <property name="deleteInvalidSessions" value="true"/>
    22. <property name="sessionListeners">
    23. <list>
    24. <ref bean="shiroSessionListener"/>
    25. list>
    26. property>
    27. <property name="sessionIdCookie" ref="sessionIdCookie"/>
    28. <property name="sessionIdUrlRewritingEnabled" value="false"/>
    29. bean>

    3)测试结果

    当登录发送请求 会执行 监听器中的 onstart

    当登出发送请求 会执行 监听器中的 onStop

    当检查session过期时,会执行 监听器中的 onExpiration

    过期时,需要身份验证才能访问的方法,就不会被允许访问;


    二、缓存管理

    ①.为什么要使用缓存

      在没有使用缓存的情况下,我们每次发送请求都会调用一次doGetAuthorizationInfo方法来进行用户的授权操作,但是我们知道,一个用户具有的权限一般不会频繁的修改,也就是每次授权的内容都是一样的,所以我们希望在用户登录成功的第一次授权成功后将用户的权限保存在缓存中,下一次请求授权的话就直接从缓存中获取,这样效率会更高一些。

    ②.什么是ehcache

      Ehcache是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大。是Hibernate中默认CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。

    ③使用缓存框架优化Shiro授权功能步骤:

    1)导入Pom依赖

    1. <dependency>
    2. <groupId>net.sf.ehcachegroupId>
    3. <artifactId>ehcacheartifactId>
    4. <version>${ehcache.version}version>
    5. dependency>
    6. <dependency>
    7. <groupId>org.slf4jgroupId>
    8. <artifactId>slf4j-apiartifactId>
    9. <version>${slf4j-api.version}version>
    10. dependency>
    11. <dependency>
    12. <groupId>org.slf4jgroupId>
    13. <artifactId>jcl-over-slf4jartifactId>
    14. <version>${slf4j-api.version}version>
    15. <scope>runtimescope>
    16. dependency>

    2)导入ehcache.xml

    1. "1.0" encoding="UTF-8"?>
    2. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
    4. updateCheck="false">
    5. <diskStore path="D://xxx"/>
    6. <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
    7. timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
    8. <cache name="com.javaxl.one.entity.User" eternal="false" maxElementsInMemory="100"
    9. overflowToDisk="true" diskPersistent="true" timeToIdleSeconds="0"
    10. timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>
    11. ehcache>

    3)添加工具类EhcacheUtil

    1. package com.zq.ssm.util;
    2. import net.sf.ehcache.Cache;
    3. import net.sf.ehcache.CacheManager;
    4. import net.sf.ehcache.Element;
    5. import java.io.InputStream;
    6. public class EhcacheUtil {
    7. private static CacheManager cacheManager;
    8. static {
    9. try {
    10. InputStream is = EhcacheUtil.class.getResourceAsStream("/ehcache.xml");
    11. cacheManager = CacheManager.create(is);
    12. } catch (Exception e) {
    13. throw new RuntimeException(e);
    14. }
    15. }
    16. private EhcacheUtil() {
    17. }
    18. public static void put(String cacheName, Object key, Object value) {
    19. Cache cache = cacheManager.getCache(cacheName);
    20. if (null == cache) {
    21. //以默认配置添加一个名叫cacheName的Cache
    22. cacheManager.addCache(cacheName);
    23. cache = cacheManager.getCache(cacheName);
    24. }
    25. cache.put(new Element(key, value));
    26. }
    27. public static Object get(String cacheName, Object key) {
    28. Cache cache = cacheManager.getCache(cacheName);
    29. if (null == cache) {
    30. //以默认配置添加一个名叫cacheName的Cache
    31. cacheManager.addCache(cacheName);
    32. cache = cacheManager.getCache(cacheName);
    33. }
    34. Element element = cache.get(key);
    35. return null == element ? null : element.getValue();
    36. }
    37. public static void remove(String cacheName, Object key) {
    38. Cache cache = cacheManager.getCache(cacheName);
    39. cache.remove(key);
    40. }
    41. }

    4)修改授权

    1. package com.zq.ssm.shiro;
    2. import com.zq.ssm.biz.UserBiz;
    3. import com.zq.ssm.model.User;
    4. import com.zq.ssm.util.EhcacheUtil;
    5. import org.apache.shiro.authc.AuthenticationException;
    6. import org.apache.shiro.authc.AuthenticationInfo;
    7. import org.apache.shiro.authc.AuthenticationToken;
    8. import org.apache.shiro.authc.SimpleAuthenticationInfo;
    9. import org.apache.shiro.authz.AuthorizationInfo;
    10. import org.apache.shiro.authz.SimpleAuthorizationInfo;
    11. import org.apache.shiro.realm.AuthorizingRealm;
    12. import org.apache.shiro.subject.PrincipalCollection;
    13. import org.apache.shiro.util.ByteSource;
    14. import java.util.Set;
    15. public class MyRealm extends AuthorizingRealm{
    16. private UserBiz userBiz;
    17. public UserBiz getUserBiz() {
    18. return userBiz;
    19. }
    20. public void setUserBiz(UserBiz userBiz) {
    21. this.userBiz = userBiz;
    22. }
    23. @Override
    24. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    25. System.out.println("用户授权。。。");
    26. String username = principals.getPrimaryPrincipal().toString();
    27. //先从缓存中 缓存中没有,在查询数据库 查询出数据放入缓存
    28. String cacheName1 = "user:role:"+username;
    29. String cacheName2 = "user:per:"+username;
    30. //转成字符形式
    31. //用户
    32. //User user = userBiz.queryByName(username);
    33. //拿到角色id
    34. //从缓存中获取角色
    35. Set roleIds = (Set) EhcacheUtil.get(cacheName1,username);
    36. //拿到角色权限
    37. //从缓存中获取权限
    38. Set perIds = (Set) EhcacheUtil.get(cacheName2,username);
    39. if(roleIds==null||roleIds.size()==0){
    40. roleIds = userBiz.getPersByUserId(username);
    41. System.out.println("从数据库中读取用户角色。。。。");
    42. }
    43. if(perIds==null||perIds.size()==0){
    44. perIds = userBiz.getPersByUserId(username);
    45. System.out.println("从数据库中读取用户权限。。。。");
    46. }
    47. //授权
    48. SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
    49. //角色
    50. info.setRoles(roleIds);
    51. //权限
    52. info.setStringPermissions(perIds);
    53. return info;
    54. }
    55. @Override
    56. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    57. System.out.println("身份认证...");
    58. String username = token.getPrincipal().toString();
    59. //String password = token.getCredentials().toString();
    60. User user = userBiz.queryByName(username);
    61. // 拿到数据库中的用户信息,放入token凭证中,用于controler进行对比
    62. AuthenticationInfo info = new SimpleAuthenticationInfo(
    63. user.getUsername(),
    64. user.getPassword(),
    65. ByteSource.Util.bytes(user.getSalt()),
    66. this.getName()
    67. );
    68. return info;
    69. }
    70. }

  • 相关阅读:
    Redis新操作
    【日常训练】871. 最低加油次数
    解决vue中接收到后端图片路径传值相同
    Hadoop生态之Kafka(一)
    泽众TestOne自动化测试平台,挡板测试(Mock测试)上线了!!
    常用的国外邮箱服务有哪些?
    MySQL 高级(进阶) SQL 语句 (一)
    ADS8866 ADC转换芯片驱动调试
    基于FPGA的VGA协议实现
    扎实打牢数据结构算法根基,从此不怕算法面试系列之week01 02-09 测试算法时间复杂度性能的方式方法
  • 原文地址:https://blog.csdn.net/weixin_66110079/article/details/126578838