shiro處理ajax請求session失效跳轉

最近在學習shiro時遇到一個問題,在ajax請求時,若是session失效時,沒法正確的跳轉登陸頁面。在以前的項目中處理的方法是經過自定義一個過濾器來處理,session失效時返回錯誤碼來處理。但由於使用shiro後,會先執行shiro定義的過濾器,纔會執行自定義的過濾器,因此以前的方法行不通,參考了不少大大的博客,把個人處理方法貼上。javascript

1.自定義攔截器LoginFormFilter攔截器,繼承FormAuthenticationFilter類,在須要登陸而未登陸的請求都會執行onAccessDenied請求。css

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請求的話,也沒法跳轉。java

2.shiro的配置類中配置攔截器。(此處使用了spring boot)jquery

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過濾器。web

3.前臺js中全局捕獲這個aja求返回的錯誤碼。ajax

$.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便可。spring

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.效果圖:apache

相關文章
相關標籤/搜索