本问题解决方案参照网站多篇文章融合解决,在此表示感谢!
环境: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);};
这个地方要根据个人情况修改一下:
Shiro:ajax的session超时处理
原文地址:http://www.cnblogs.com/huiy/p/7497954.html