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;
  }

这个是重点:

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);
};

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

时间: 2024-09-30 20:55:54

Shiro:ajax的session超时处理的相关文章

Ajax请求Session超时解决

web前端js代码: $.ajaxSetup({ contentType : "application/x-www-form-urlencoded;charset=utf-8", complete : function(xhr, textStatus) { if (xhr.status == 520) {//如果返回状态码是520 window.location..reload();//刷新页面,执行登录逻辑 return; } } }); java代码: 1. 写一个filter i

ajax提交session超时跳转页面使用全局的方法来处理

来自:http://www.jb51.net/article/43770.htm 如果是ajax提交,超时时从服务器发出的跳转命令就不会起作用,所以如果是session超时,而且是在ajax请求,就在响应头里,再用一个全局的方法来处理session超时要跳转的页面. 在过滤器中写入如下方法:(未测试) public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws I

webix+springmvc session超时跳转登录页面

2016-10-30 13:11:56 引言 最近做项目,发现ajax请求不能在服务器中直接重定向到登录页面.查了些资料发现jquery的ajax请求有人给出了方法.但是webix的ajax请求和jquery的有些区别.这里模仿jquery的处理方式实现webix的ajax请求session超时跳转. 具体的做法: 1.查看webix.js源码发现webix.ajax只有请求前的监听函数 "onBeforeAjax", 要做到获取返回状态跳转登录页面必须要有个返回的监听函数,但是源码没

ajax session超时处理

1.问题:  客户端发出了一个ajax请求,但是此时session超时了 2.解决方法: 服务端: 在过滤器或者拦截器中,判断ajax请求类型,设置一个超时标志 客户端:ajax请求要求有一个全局处理函数 ,获取相应标志,做出相应处理   过滤器中加入: // 如果是ajax请求响应头会有,x-requested-with: if (req.getHeader("x-requested-with") != null && req.getHeader("x-re

spring mvc session超时,处理ajax请求

做web开发时,当session超时时,如果不是ajax请求,很简单就能实现跳到指定的页面.但是ajax请求就会有问题.session超时的时候,点击到ajax请求就会弹出一些页面源码文件. 首先建了个拦截器,来判断session超时.用户登录后会保存用户信息在一个session里,在session的监听里,session超时会销毁保存在session里的用户信息,而拦截器就通过session里是否有用户信息来判断session超时. 拦截器是spring-mvc的拦截器,在拦截器里判断是不是a

解决spring-security session超时 Ajax 请求没有重定向的问题

开始时, 代码是这样的: $.ajax({ type : "POST", url : sSource, cache : false, dataType : "json", data : aoData, success : function(resp) { alert(11) fnCallback(resp); $.dialog.tips('数据加载完毕', 1, 'success.gif', function() { }); } }); spring-securit

PHP jquery session超时处理

php: <?php header('sessionStatus:timeOut'); //is_ajax echo $_SERVER['HTTP_X_REQUESTED_WITH']; html:<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <script type="text/javascript" sr

esayui session 超时跳转登录页面

 代码部分: ① web.XML部分配置代码 <!-- filter 权限认证 只对amf请求过滤 --><filter> <filter-name>authFilter</filter-name> <filter-class>com.lactec.framework.ac.filter.AuthFilter</filter-class></filter> <filter-mapping> <filter

jQuery easyui Session 超时返回登录页面

说明:测试设置失效时间为1分钟,登录成功后1分钟去点击操作处罚事件,执行①连接到com.lactec.framework.ac.filter.AuthFilter这个类判断执行的action操作. 判断session是否为空,超时就返回,我用的是ajax请求:如果是ajax请求响应头会有,x-requested-with: 设置: rep.setHeader("sessionstatus", "timeout");//在响应头设置session状态