当前位置 博文首页 > 快乐的小三菊的博客:springboot shiro session过期跳转到登录页

    快乐的小三菊的博客:springboot shiro session过期跳转到登录页

    作者:[db:作者] 时间:2021-07-28 20:46

    背景:

    ? ? ? ?想实现一个 session 过期,然后系统自动校验,然后跳转到登录页的功能,研究了好几天,终于研究出来了。

    编写拦截器:

    ? ? ? ?需要编写一个拦截器?ClearSessionCacheFilter?来拦截用户的 ajax 请求,若当前的 session 处于超时状态,则给他设置?session-status 为?timeout ,然后在 js 文件里面做一个校验即可。

    public class ClearSessionCacheFilter implements Filter{
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    		
    	}
    
    	@Override
    	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
    			throws IOException, ServletException {
    		HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            String basePath = request.getContextPath();
            request.setAttribute("basePath", basePath);
            // 判断 session 里是否有用户信息
            if (!SecurityUtils.getSubject().isAuthenticated()) {
            	 // 如果是ajax请求响应头会有,x-requested-with
                if (request.getHeader("x-requested-with") != null
                        && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
            		// 在响应头设置session状态
                    response.setHeader("session-status", "timeout");
                    return;
                }
            }
            filterChain.doFilter(request, servletResponse);
    	}
    
    	@Override
    	public void destroy() {
    		
    	}
    }

    配置 ShiroConfig :

    ? ? ? ?需要将上面新增的?ClearSessionCacheFilter?配置到?ShiroConfig 中,代码如下所示:

        /**
    	 * 校验当前缓存是否失效的拦截器
    	 * 
    	 * */
    	@Bean
    	public ClearSessionCacheFilter clearSessionCacheFilter() {
    		ClearSessionCacheFilter clearSessionCacheFilter = new ClearSessionCacheFilter();
    		return clearSessionCacheFilter;
    	}
    
        // Filter工厂,设置对应的过滤条件和跳转条件
    	@Bean
    	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    		ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
    		// Shiro的核心安全接口,这个属性是必须的
    		shiroFilter.setSecurityManager(securityManager);	
    	
    		//不输入地址的话会自动寻找项目web项目的根目录下的/page/login.jsp页面。
    		shiroFilter.setLoginUrl("/login");
    		//登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。
    		//shiroFilter.setSuccessUrl("/");
    		
    		// 自定义拦截器处理session过期的操作
    	    LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();	  
    	    filtersMap.put("clearSession", SystemFilter());
    	    shiroFilter.setFilters(filtersMap);
    	    
    		//没有权限默认跳转的页面
    		//shiroFilter.setUnauthorizedUrl("");
    		
    		//filterChainDefinitions的配置顺序为自上而下,以最上面的为准
    		//shiroFilter.setFilterChainDefinitions("");
            // Shiro验证URL时,URL匹配成功便不再继续匹配查找(所以要注意配置文件中的URL顺序,尤其在使用通配符时),配置不会被拦截的链接 顺序判断
    		Map<String, String> map = new LinkedHashMap<>();
    		
    		// 不能对login方法进行拦截,若进行拦截的话,这辈子都登录不上去了,这个login是LoginController里面登录校验的方法
    		map.put("/login", "anon"); 
    		map.put("/static/**", "anon");
    		//map.put("/", "anon");
    		//对所有用户认证
    		map.put("/**", "clearSession,authc");
    		
    		shiroFilter.setFilterChainDefinitionMap(map);
    		return shiroFilter;
    	}

    前端代码:

    ? ? ? 在我们平常的项目中,一般都会引入一些公共的 js 文件,在里面添加一些常用的工具方法或者常量,这时我们需要在 js 文件中添加一个 ajax 的父级方法?$.ajaxSetup ,用于拦截ajax 返回后的数据,用于校验当前的 session 是否处于过期状态,若处于过期状态则跳转到首页,代码如下所示:

    function addRoleIds(){
    
    	$.ajax({
    		url :"addRoleIds",
    		data : {"userName" : "lisi"} ,
    		async:false,
    		type : "get",
    		success : function(data) {
    			alert(data);
    		}
    	})
    }
    
    function delRoleIds(){
    
    	$.ajax({
    		url :"delRoleIds",
    		data : {"userName" : "zhangsan"} ,
    		async:false,
    		type : "get",
    		success : function(data) {
    			alert(data);
    		},
    
    	})
    }
    $.ajaxSetup({
    	complete:function(XMLHttpRequest,textStatus){
    		var sessionstatus=XMLHttpRequest.getResponseHeader("session-status");
    		if(sessionstatus == "timeout"){
    			alert("会话超时,请重新登录!")
    			//如果超时就处理 ,指定要跳转的页面
    			window.location.href= "/login";
    		}		
    	}
    });

    ?

    cs