shiro中session的使用

下图是shiro中session的存放使用逻辑

使用shiro中的session的步骤
一、创建SessionFactory的实现类,实现createSession方法
@Override
public Session createSession(SessionContext initData){
OnlineSession session = new OnlineSession();
if (initData != null && initData instanceof WebSessionContext)
{
WebSessionContext sessionContext = (WebSessionContext) initData;
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
if (request != null)
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
session.setHost(IpUtils.getIpAddr(request));
session.setBrowser(browser);
session.setOs(os);
}
}
return session;
}

二、创建OnlineSessionDAO类,继承EnterpriseCacheSessionDAO,重写doReadSession,update,doDelete三个方法
通过 service查询数据库中是否存在
@Override
protected Session doReadSession(Serializable sessionId)
{
return sysShiroService.getSession(sessionId);
}

@Override
public void update(Session session) throws UnknownSessionException
{
    super.update(session);
}

//删除数据库中的session数据
@Override
protected void doDelete(Session session)
{
OnlineSession onlineSession = (OnlineSession) session;
if (null == onlineSession)
{
return;
}
onlineSession.setStatus(OnlineStatus.off_line);
sysShiroService.deleteSession(onlineSession);
}

三、创建OnlineSession类继承SimpleSession类,添加用户id,登录名、部门...我们的用户对象相关必要属性
@Data
public class OnlineSession extends SimpleSession {
private static final long serialVersionUID = 1L;

/**
 * 用户ID
 */
private Long userId;

/**
 * 用户名称
 */
private String loginName;

/**
 * 部门名称
 */
private String deptName;

/**
 * 用户头像
 */
private String avatar;

/**
 * 浏览器类型
 */
private String browser;

/**
 * 操作系统
 */
private String os;

/**
 * 在线状态
 */
private OnlineStatus status = OnlineStatus.on_line;

/**
 * 属性是否改变 优化session数据同步
 */
private transient boolean attributeChanged = false;

public void markAttributeChanged() {
    this.attributeChanged = true;
}

public void resetAttributeChanged() {
    this.attributeChanged = false;
}

public boolean isAttributeChanged() {
    return attributeChanged;
}

@Override
public void setAttribute(Object key, Object value) {
    super.setAttribute(key, value);
}

@Override
public Object removeAttribute(Object key) {
    return super.removeAttribute(key);
}

}

四、将sessionDAO和SessionFactory注入到SecurityManager中
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealms(Arrays.asList(userRealm));
DefaultWebSessionManager manager = new DefaultWebSessionManager();
manager.setSessionDAO(sessionDAO());
// // 自定义sessionFactory
manager.setSessionFactory(sessionFactory());
securityManager.setSessionManager(sessionManager());

五、使用filter拦截请求
/**

  • 自定义访问控制
    /
    @Slf4j
    public class OnlineSessionFilter extends AccessControlFilter {
    /
    *

    • 强制退出后重定向的地址
      */
      @Value("${shiro.user.loginUrl}")
      private String loginUrl;

    private OnlineSessionDAO onlineSessionDAO;

    /**

    • 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
      */
      @Override
      protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
      throws Exception {

      String userKey = "";
      try {
      String token = JwtUtil.getToken();
      if (StringUtils.isNotEmpty(token)) {
      String uuid = JwtUtil.getSubJectFromToken(token);
      // 解析对应的权限以及用户信息
      if (StringUtils.isBlank(uuid)) {
      throw new Exception("user no login...");
      }
      userKey = JwtUtil.getTokenKey(uuid);
      }
      } catch (Exception e) {
      log.error("获取用户信息异常'{}'", e.getMessage());
      }
      Subject subject = getSubject(request, response);
      Session session = onlineSessionDAO.readSession(subject.getSession().getId());

      if (session != null && session instanceof OnlineSession) {
      // session = onlineSessionDAO.readSession(userKey);
      OnlineSession onlineSession = (OnlineSession) session;
      request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
      // 把user对象设置进去
      boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
      if (isGuest == true) {
      SysUser user = ShiroUtils.getSysUser();
      if (user != null) {
      onlineSession.setUserId(user.getUserId());
      onlineSession.setLoginName(user.getLoginName());
      onlineSession.setAvatar(user.getAvatar());
      onlineSession.setDeptName(user.getDept().getDeptName());
      onlineSession.markAttributeChanged();
      }
      }

       if (onlineSession.getStatus() == OnlineStatus.off_line) {
           return false;
       }
      

      }

      return true;
      }

    /**

    • 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
      */
      @Override
      protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
      Subject subject = getSubject(request, response);
      if (subject != null) {
      subject.logout();
      }
      saveRequestAndRedirectToLogin(request, response);
      return false;
      }

    // 跳转到登录页
    @Override
    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
    WebUtils.issueRedirect(request, response, loginUrl);
    }

    public void setOnlineSessionDAO(OnlineSessionDAO onlineSessionDAO) {
    this.onlineSessionDAO = onlineSessionDAO;
    }
    }

posted @   vello  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示