org.apache.shiro.SecurityUtils.getSubject().getSession()

本文详细介绍了Shiro Session管理的概述、基本使用、SessionManager、设置过期时间、事件监听、SessionDAO配置以及Web应用中的Session管理。此外,还讨论了如何自定义SessionDAO以满足特定需求。

Shiro的Session管理 概述和配置使用

1.概述

  Shiro提供安全框架界独一无二的东西:一个完整的企业级Session 解决方案,可以为任意的应用提供session支持,包括web和非web应用,并且无需部署你的应用程序到Web 容器或使用EJB容器。

2.基本使用

  可以通过与当前执行的Subject 交互来获取Session:

Subject currentUser = SecurityUtils.getSubject();  

 Session session = currentUser.getSession();

 session.setAttribute("someKey", someValue);

3关于SessionManager

  SessionManager是用来管理Session的组件,包括:创建,删除,inactivity(失效)及验证,等等。SessionManager 也是一个由  SecurityManager 维护的顶级组件。

  shiro提供了默认的SessionManager实现,一般没有必要自定义这个。

4.设置Sessioin的过期时间

  Shiro 的SessionManager 实现默认是30 分钟会话超时。

  你可以设置SessionManager 默认实现的globalSessionTimeout 属性来为所有的会话定义默认的超时时间。例如,

# 3,600,000 milliseconds = 1 hour
securityManager.sessionManager.globalSessionTimeout = 3600000

5.Sessioin的事件监听

      你可以实现SessionListener 接口(或扩展易用的SessionListenerAdapter)并与相应的会话操作作出反应。 配置示例:

aSessionListener = com.foo.my.SessionListener

anotherSessionListener = com.foo.my.OtherSessionListener

securityManager.sessionManager.sessionListeners = $aSessionListener, $anotherSessionListener

6.SessionDAO

6.1概述

  每当一个会话被创建或更新时,它的数据需要持久化到一个存储位置以便它能够被稍后的应用程序访问,实现这个功能的组件就是SessionDAO。

  你能够实现该接口来与你想要的任何数据存储进行通信。这意味着你的会话数据可以驻留在内存中,文件系统,关系数据库或NoSQL 的数据存储,或其他任何你需要的位置。

6.2基本配置 
  SessionDAO是作为一个属性配置在默认的SessionManager 实例上

sessionDAO = com.foo.my.SessionDAO

securityManager.sessionManager.sessionDAO = $sessionDAO

 这种SessionDAO主要在本地应用中起作用。

基于EHCache的SessionDAO,基本配置如下:

sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO

securityManager.sessionManager.sessionDAO = $sessionDAO

cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager

securityManager.cacheManager = $cacheManager

7.Shiro提供了默认的EHCache的配置xml,如果你要配置自己的EHCache.xml,需要注意以下几点:

7.1  overflowToDisk=“true” - 这确保当你溢出进程内存时,会话不丢失且能够被序列化到磁盘上。

7.2 eternal=“true” - 确保缓存项(Session 实例)永不过期或被缓存自动清除。这是很有必要的,因为Shiro 基于计划过程完成自己的验证。如果我们关掉这项,缓存将会在Shiro 不知道的情况下清扫这些Sessions,这可能引起麻烦。

7.3 如果你想使用一个不同的名字而不是默认的,你可以在EnterpriseCacheSessionDAO 上配置名字,例如:sessionDAO.activeSessionsCacheName = myname

只要确保在ehcahe.xml 中有一项与这个名字匹配

8.Web应用中的Session

       在web应用上,默认使用的是容器的会话,如果你想基于Web 应用程序启用SessionDAO 来自定义会话存储或会话群集,你将不得不首先配置一个本地的Web 会话管理器。例如:

sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager

securityManager.sessionManager = $sessionManager

# Configure a SessionDAO and then set it:

securityManager.sessionManager.sessionDAO = $sessionDAO

在web应用上,如果想要在每一个请求的基础上启用或禁用会话的创建,可以在配置中的[urls] 里面,为相应的url设置一个noSessionCreation过滤器,如下:

[urls]

/rest/** = noSessionCreation, authcBasic

9.自定义SessionDAO

       在某些场景中,我们需要管理用户的Session信息,比如把Session信息放到数据库中,这样就可以记录一个操作日志,或是统计在线人员等等。

       自定义SessionDAO也非常简单,通常是继承AbstractSessionDAO,实现对Session数据的CRUD即可,简单示例如下:

public class MySessionDAO extends AbstractSessionDAO{

private Map<Serializable,Session> map = new HashMap<Serializable,Session>();

  public void update(Session session) throws UnknownSessionException {

  System.out.println("now update session");

  map.put(session.getId(),session);

  }

  public void delete(Session session) {

  System.out.println("now delete session"); 

  map.remove(session.getId());

  }

  public Collection<Session> getActiveSessions() {

  System.out.println("now getActiveSessions session");

  return map.values();

  }

  

  protected Serializable doCreate(Session session) {

  System.out.println("now doCreate session");

  Serializable sessionId = generateSessionId(session);

      assignSessionId(session, sessionId);

      map.put(sessionId, session);

    

     return sessionId;

  }

  protected Session doReadSession(Serializable sessionId) {

  System.out.println("now doReadSession session");

  return map.get(sessionId);

  }

}

基本的配置示例:


sessionDAO = cn.javass.hello.MySessionDAO

securityManager.sessionManager.sessionDAO = $sessionDAO

使用shirossion时需要把配置中存session的地方改成本地机或者是ip才可以取到,shirosession比session稳定

 

sessionId.cookie.domain=localhost

package com.nbp.df.agent.admin.api.shiro; import com.nbp.df.agent.admin.api.sys.service.BackWebTokenService; import com.nbp.df.agent.admin.api.sys.service.ShiroService; import com.nbp.df.agent.admin.configuration.ContextHelper; import com.nbp.df.agent.admin.constant.Constant; import com.nbp.df.agent.admin.constant.SysRestConstants; import com.nbp.df.agent.admin.exception.ReturnCodes; import com.nbp.df.agent.admin.util.BeanCopyUtils; import com.nbp.df.agent.common.redis.RedisUtils; import com.nbp.df.sys.manager.SysUserManager; import com.nbp.df.sys.model.SysUser; import com.nbp.df.sys.model.SysUserQuery; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Set; /** * shiro认证 * * @author yuliang * * @version 1.0 */ @Component public class ShiroRealm extends AuthorizingRealm { private static final Logger log = LoggerFactory .getLogger(RedisUtils.class); @Autowired BackWebTokenService backWebTokenService; @Autowired SysUserManager sysUserManager; @Autowired ShiroService shiroService; /** * 用户信息 * */ public SysUser getSubject() { String webToken = (String) SecurityUtils.getSubject().getPrincipal(); SysUser sysUserDto = backWebTokenService.validateWebToken(webToken); if(sysUserDto != null) { SysUserQuery sysUserQuery = BeanCopyUtils.getMapperFacade().map(sysUserDto, SysUserQuery.class); sysUserDto = sysUserManager.selectOne(sysUserQuery); } return sysUserDto; } public void authSuperValidHandler(){ SysUser sysUserDto = this.getSubject(); if(sysUserDto != null) { if(Constant.NO_INT == sysUserDto.getSuperAdmin() || !Constant.SUPER_ADMIN.equals(sysUserDto.getId())) { ReturnCodes.SYS_BACKSTAGE_19099.generateException(); } } } public void authValidHandler(){ SysUser sysUserDto = this.getSubject(); if(sysUserDto != null) { } } /** * 权限认证 * */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { /** 1.根据token缓存获取userId **/ String webToken = (String) SecurityUtils.getSubject().getPrincipal(); Session session = SecurityUtils.getSubject().getSession(); session.setAttribute("key", "123456789"); SysUser sysUserDto = backWebTokenService.validateWebToken(webToken); /** 2.获取该用户下的权限列表 **/ SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); Set<String> set = shiroService.queryAllPermsByUserId(sysUserDto.getId()); info.setStringPermissions(set); return info; } /** * 用户身份认证 * */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String webToken = (String) token.getPrincipal(); log.info("接口请求token获取:"+webToken); Boolean flag = false; /** 1.根据token缓存获取userId,判断是否失效 **/ SysUser sysUserDto = backWebTokenService.validateWebToken(webToken); if (sysUserDto == null) { flag = true; } /** 2.根据userId,激活状态获取用户相关信息,判断是否失效 **/ if(!flag) { SysUserQuery query = new SysUserQuery(); query.setId(sysUserDto.getId()); query.setStatus(Constant.YES_INT); sysUserDto = sysUserManager.selectOne(query); if (sysUserDto == null) { flag = true; } } /** 3.发生异常 **/ if (flag) { /** 发生异常,保存异常栈 **/ ContextHelper.getRequest().setAttribute("ex", ReturnCodes.SYS_BACKSTAGE_19014); /** 异常转发,统一异常处理 **/ try { ContextHelper.getRequest().getRequestDispatcher(SysRestConstants.SHIRO_FILTER_EXCEPTION_FORWARD_URL).forward(ContextHelper.getRequest(), ContextHelper.getResponse()); return null; } catch (IOException e) { e.printStackTrace(); } catch (jakarta.servlet.ServletException e) { throw new RuntimeException(e); } } return new SimpleAuthenticationInfo(webToken, webToken, getName()); } } package com.nbp.df.agent.admin.configuration; import com.nbp.df.agent.admin.api.shiro.ShiroRealm; import com.nbp.df.agent.admin.filter.ShiroFilter; import com.nbp.df.agent.admin.listener.ShiroSessionListener; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.SessionListener; import org.apache.shiro.session.mgt.eis.MemorySessionDAO; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import javax.servlet.Filter; import java.util.*; /** * shiro配置类 * * @author yuliang * * @version 1.0 */ @Configuration public class ShiroConfig { @Bean public SessionDAO sessionDAO() { return new MemorySessionDAO(); } @Bean public DefaultWebSessionManager sessionManager() { //配置默认的sesssion管理器 DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(60 * 60 * 1000); sessionManager.setSessionDAO(sessionDAO()); Collection<SessionListener> listeners = new ArrayList<SessionListener>(); listeners.add(new ShiroSessionListener()); sessionManager.setSessionListeners(listeners); return sessionManager; } @Bean public SecurityManager securityManager(ShiroRealm shiroRealm) { DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(); defaultSecurityManager.setSessionManager(sessionManager()); defaultSecurityManager.setRealm(shiroRealm); defaultSecurityManager.setSessionManager(sessionManager()); ThreadContext.bind(defaultSecurityManager); // FIXME 添加自定义缓存 return defaultSecurityManager; } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); // shiroFilterFactoryBean.setLoginUrl("/login"); // shiroFilterFactoryBean.setUnauthorizedUrl("/user/user_login/notRole"); Map<String, Filter> filters = new HashMap<>(); filters.put("oauth2", new ShiroFilter()); shiroFilterFactoryBean.setFilters(filters); Map<String, String> filterMap = new LinkedHashMap<>(); /** filterException **/ filterMap.put("/filterException/**", "anon"); /** sys login **/ filterMap.put("/sys/login/v1.0.0/login", "anon"); // 定义需要身份认证url /*filterMap.put("/sys/**", "oauth2")*/; filterMap.put("/**", "oauth2"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); return shiroFilterFactoryBean; } @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean @DependsOn({"lifecycleBeanPostProcessor"}) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } } doGetAuthenticationInfo 没有生效
08-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值