zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    2017-2018-1 20155311 《信息安全系统设计基础》第5周学习总结
    2017-2018-1 20155311 《信息安全系统设计基础》第3周学习总结
    2017-2018-1 20155311 《信息安全系统设计基础》第4周学习总结
    2017-2018-1 20155311 《信息安全系统设计基础》第2周学习总结
    2017-2018-1 20155311 《信息安全系统设计基础》第1周学习总结
    20155308&20155316 2017-2018-1 《信息安全系统设计基础》实验三
    20155308 加分项——C语言实现Linux的pwd命令
    2017-2018-1 20155308 《信息安全系统设计基础》第九周学习总结
    2017-2018-1 20155308&20155321&20155330《信息安全技术》实验三——数字证书应用1
    2017-2018-1 20155308 《信息安全系统设计基础》第八周学习总结
  • 原文地址:https://www.cnblogs.com/huiy/p/7497954.html
Copyright © 2011-2022 走看看