本问题解决方案参照网站多篇文章融合解决,在此表示感谢!
环境: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