当前位置: 首页 > news >正文

Shiro:ajax的session超时处理

本问题解决方案参照网站多篇文章融合解决,在此表示感谢!

环境:springboot+shiro+jquery-easyui

问题:在ajax请求时,如果此时session已经失效,系统没有自动跳转到登录页面。后来在服务端加了判断ajax请求的代码,结果还是没有用,无法取到ajax特定的head值(X-Requested-With)。发现jquery-easyui表单提交时没有就没有传递这个值。

解决办法:

1.添加拦截器

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SessionFilter extends FormAuthenticationFilter {

  private Logger logger = LoggerFactory.getLogger(SessionFilter.class);
  private final static String X_REQUESTED_WITH_STRING = "X-Requested-With";
  private final static String XML_HTTP_REQUEST_STRING = "XMLHttpRequest";
  private final static String SESSION_OUT_STIRNG = "sessionOut";

  @Override
  protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
    if (this.isLoginRequest(servletRequest, servletResponse)) {
      if (this.isLoginSubmission(servletRequest, servletResponse)) {
        return this.executeLogin(servletRequest, servletResponse);
      } else {
        return true;
      }
    } else {
      if (isAjax((HttpServletRequest) servletRequest)) {
        servletResponse.getWriter().print(SESSION_OUT_STIRNG);
      } else {
        this.saveRequestAndRedirectToLogin(servletRequest, servletResponse);
      }
      return false;
    }
  }

  public boolean isAjax(HttpServletRequest httpServletRequest) {
    String header = httpServletRequest.getHeader(X_REQUESTED_WITH_STRING);
    if (XML_HTTP_REQUEST_STRING.equalsIgnoreCase(header)) {
      logger.debug("当前请求为Ajax请求:{}", httpServletRequest.getRequestURI());
      return Boolean.TRUE;
    }
    logger.debug("当前请求非Ajax请求:{}", httpServletRequest.getRequestURI());
    return Boolean.FALSE;
  }

}

2.覆盖默认shiro拦截器

@Bean
  public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // 必须设置 SecurityManager
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
    shiroFilterFactoryBean.setLoginUrl("/login");
    // 登录成功后要跳转的链接
    shiroFilterFactoryBean.setSuccessUrl("/index");
    // 未授权界面;
    shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    // 自定义拦截器
    Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
    // 限制同一帐号同时在线的个数。
    filtersMap.put("kickout", filterKickoutSessionControl());
    shiroFilterFactoryBean.setFilters(filtersMap);
    // 权限控制map.
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
    filterChainDefinitionMap.put("/servlet/authimage", "anon");
    filterChainDefinitionMap.put("/**", "authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    Map<String, Filter> filters=new LinkedHashMap<>();
    filters.put("authc", new SessionFilter());
    shiroFilterFactoryBean.setFilters(filters);
    return shiroFilterFactoryBean;
  }

这个是重点,覆盖shiro默认的拦截器:

Map<String, Filter> filters=new LinkedHashMap<>();
    filters.put("authc", new SessionFilter());
    shiroFilterFactoryBean.setFilters(filters);

3.改造前端

一开始采用了修改form提交的参数,把iframe=false就可以提交X-Requested-With,但是这样的异步请求实在太多,不仅仅在form提交,还有combo,tree等等。所以最后用了网上说的方法,改造$.ajax达到统一处理。

//首先备份下jquery的ajax方法  
var _ajax = $.ajax;
// 重写jquery的ajax方法
$.ajax = function(opt) {
    // 备份opt中error和success方法
    var fn = {
        error : function(XMLHttpRequest, textStatus, errorThrown) {
        },
        success : function(data, textStatus) {
        }
    }
    if (opt.error) {
        fn.error = opt.error;
    }
    if (opt.success) {
        fn.success = opt.success;
    }

    // 扩展增强处理
    var _opt = $.extend(opt, {
        error : function(XMLHttpRequest, textStatus, errorThrown) {
            debugger;
            erro = eval("(" + XMLHttpRequest.responseText + ")");
            // 错误方法增强处理
            fn.error(XMLHttpRequest, textStatus, errorThrown);
        },
        success : function(data, textStatus) {
            if (data != 'sessionOut') {
                fn.success(data, textStatus)
                return false;
            } else {
                top.location.href = appPath + "/";
            }
        }
    });
    return _ajax(_opt);
};

这个地方要根据个人情况修改一下:

image

转载于:https://www.cnblogs.com/huiy/p/7497954.html

相关文章:

  • cogs2223 [SDOI2016 Round1] 生成魔咒
  • Sql 时间做条件
  • SQL Server 数据库中的几个常见的临界值
  • A Research Problem UVA - 10837 欧拉函数逆应用
  • 洛谷P2344 奶牛抗议
  • python归档:笔记转化
  • 理解JS中的call、apply、bind方法
  • Number Math
  • 初学JAVA的变量作用域
  • Inno Setup自定义安装界面脚本
  • Spring AOP简单的配置(注解和xml配置)
  • Swift,枚举
  • java操作Excel
  • 'NoneType' object is not iterable
  • AngularJS
  • Android框架之Volley
  • CentOS 7 防火墙操作
  • iOS | NSProxy
  • JavaWeb(学习笔记二)
  • Java精华积累:初学者都应该搞懂的问题
  • Java应用性能调优
  • Nacos系列:Nacos的Java SDK使用
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • orm2 中文文档 3.1 模型属性
  • PHP 的 SAPI 是个什么东西
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • vue脚手架vue-cli
  • vue中实现单选
  • 从零搭建Koa2 Server
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 那些年我们用过的显示性能指标
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 使用 Docker 部署 Spring Boot项目
  • 推荐一个React的管理后台框架
  • 一文看透浏览器架构
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 翻译 | The Principles of OOD 面向对象设计原则
  • #每天一道面试题# 什么是MySQL的回表查询
  • (06)金属布线——为半导体注入生命的连接
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (六)vue-router+UI组件库
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (转)jQuery 基础
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • (状压dp)uva 10817 Headmaster's Headache
  • .Net多线程总结
  • .NET轻量级ORM组件Dapper葵花宝典
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .Net下的签名与混淆
  • .Net中ListT 泛型转成DataTable、DataSet