shiro处理ajax请求session失效跳转

最近在学习shiro时遇到一个问题,在ajax请求时,如果session失效时,无法正确的跳转登录页面。在之前的项目中处理的方法是通过自定义一个过滤器来处理,session失效时返回错误码来处理。但因为使用shiro后,会先执行shiro定义的过滤器,才会执行自定义的过滤器,所以之前的方法行不通,参考了很多大大的博客,把我的处理方法贴上。

1.自定义拦截器LoginFormFilter拦截器,继承FormAuthenticationFilter类,在需要登录而未登录的请求都会执行onAccessDenied请求。

package com.xxfy.demo.filter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xxfy.demo.util.HttpUtils;

public class LoginFormFilter extends FormAuthenticationFilter {
	
	private static final Logger log = LoggerFactory.getLogger(LoginFormFilter.class);

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		HttpServletRequest httpServletRequest = (HttpServletRequest)request;
		HttpServletResponse httpServletResponse = (HttpServletResponse)response;
		if (isLoginRequest(request, response)) {
            if (isLoginSubmission(request, response)) {
                if (log.isTraceEnabled()) {
                    log.trace("Login submission detected.  Attempting to execute login.");
                }
                return executeLogin(request, response);
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Login page view.");
                }
                //allow them to see the login page ;)
                return true;
            }
        } else {
            if (log.isTraceEnabled()) {
                log.trace("Attempting to access a path which requires authentication.  Forwarding to the " +
                        "Authentication url [" + getLoginUrl() + "]");
            }
            //如果是Ajax请求,不跳转登录
            if (HttpUtils.isAjax(httpServletRequest)){
    			System.out.println("ajax");
    			httpServletResponse.setStatus(401);
    		} else {
    			saveRequestAndRedirectToLogin(request, response);
    		}
            return false;
        }
	}
}

此处的onAccessDenied方法跟FormAuthenticationFilter基本类似,只是加了一段判断是ajax请求的代码 ,如果是ajax请求的话,直接返回错误码,而不是跳转登录,因为如果是ajax请求的话,也无法跳转。

2.shiro的配置类中配置拦截器。(此处使用了spring boot)

package com.xxfy.demo.config;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.xxfy.demo.filter.LoginFormFilter;

/**
 * shiro配置类
 * @author Administrator
 *
 */

@Configuration
public class ShiroConfiguration {
	
	@Bean
    public SecurityManager securityManager(){
       DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
       securityManager.setRealm(myShiroRealm());
       return securityManager;
    }
	
	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
		ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		//拦截器.
	    Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
		//配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
	    filterChainDefinitionMap.put("/logout", "logout");
	    //静态资源可以不登录访问
	   /* filterChainDefinitionMap.put("/static/**", "anon");*/
	    filterChainDefinitionMap.put("/assets/**", "anon");
	    filterChainDefinitionMap.put("/js/**", "anon");
	    filterChainDefinitionMap.put("/css/**", "anon");
	    filterChainDefinitionMap.put("/img/**", "anon");
	    filterChainDefinitionMap.put("/unauth", "anon");
	    //filterChainDefinitionMap.put("/admin/index", "roles['admin']");
	    //所有请求都需要登录才可以访问
	    filterChainDefinitionMap.put("/**", "authc");
	    
	    //登录请求
	    shiroFilterFactoryBean.setLoginUrl("/login");
	    //登录成功跳转的页面
	    shiroFilterFactoryBean.setSuccessUrl("/admin/index");
	    Map<String,Filter> filters = new HashMap<String,Filter>();
	    Filter loginFilter = new LoginFormFilter();
	    filters.put("authc", loginFilter); //此处使用自定义的拦截器,autho默认使用FormAuthenticationFilter拦截器
	    shiroFilterFactoryBean.setFilters(filters);
	    //没有权限的页面
	    shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
	    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}
	
	@Bean
	public AuthorizingRealm myShiroRealm() {
		AuthorizingRealm myRealm = new MyShiroRealm();
		myRealm.setCredentialsMatcher(customCredentialsMatcher());
		return myRealm;
	}
	
	@Bean
	public CustomCredentialsMatcher customCredentialsMatcher() {
		CustomCredentialsMatcher customCredentialsMatcher =  new CustomCredentialsMatcher();
		customCredentialsMatcher.setHashAlgorithmName("MD5");
		return customCredentialsMatcher;
	}
 
}

此处的关键就是代码就是这个:filters.put("authc", loginFilter);这里使用第一步的过滤器,shiro默认使用FormAuthenticationFilter过滤器。

3.前台js中全局捕获这个aja求返回的错误码。

$.ajaxSetup({  
       type: "POST",  
       complete: function(jqXHR, textStatus){  
           switch (jqXHR.status){  
               case(500):  
                   alert("服务器系统内部错误");  
                   break;  
               case(401):  
            	   $("#loginModal").modal("show");
                   break;  
               case(403):  
                   alert("无权限执行此操作");  
                   break;  
               case(408):  
                   alert("请求超时");  
                   break;  
               default:  
                   alert("未知错误");  
           }  
       },   
       success: function(data){  
           alert("操作成功");  
       }  
   }); 

4.增加一步无关的一步,作为自己的记录,项目使用了jquery.datatable作为数据展示,使用这种方法处理ajax请求时,如果session失效,进行查询返回的肯定就不会是json格式的数据,datatable会有一个自身的提示信息,需要把它去掉,此时只要在请求中增加error即可。

var table = $('#example').DataTable({
	   	//开启服务器模式
	    serverSide: true, 
	    //禁用搜索
	    searching: false,
	    //禁用排序
	    ordering:  false,
	   //数据来源(包括处理分页,排序,过滤) ,即url,action,接口,等等
	    ajax: {
	    	url : $("#contextPath").val() + "/admin/permissions/user/list",
	    	type:"post",
	    	data : function(d){
	    		d.userId=$("#userId").val();
	    		d.userName=$("#userName").val();
	    		d.sex=$("#sex").val();
	    		d.tel=$("#tel").val();
	    	},
	    	error:function(data) {
	    	}
	    }, 

5.效果图:

转载于:https://my.oschina.net/u/729917/blog/885421

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值