springMVC+shiro的权限管理和异常统一处理

springMVC+shiro的权限管理和异常统一处理
SpringMVC+shiro的配置请参照网上其他博文,本文主要介绍如何使用shiro,动态管控用户的url请求。如何自定义filter,让前端页面通过返回的异常状态码进行统一的弹窗提示。
使用shiro后发现,当请求不符合过滤器要求时,会自动跳转到unauthorizedUrl页面,而我想实现的是通过后端返回不同的异常状态码,前端ajax判断后进行弹窗提示,这样用户体验上会更友好一些。具体做法是通过自定义shiro的filter来实现的。
首先在shiro的配置文件中配置自定义的filter:
	
	
	
	
	
		
		
		
		
		
		
		
		
		
		
			
				
				
				
			
		
		
		
		
		
		
		
			
				/=anon
				/font/**=anon
				/login.jsp=anon
				/jcaptcha*=anon
				/images/**=anon
				/js/**=anon
				/css/**=anon
				/system/getSalt*=anon
				/loginCheck=anon
				/login=anon
				/druid=anon
				/reLogin=anon
				/index.htm=authc
				/logout.htm=authc
				/system/navigation/get=authc
				/dics/list=authc
				/**=myFilter
			
		
	
其中包含两个filter,loginFilter和MyFilter,loginFilter主要是覆盖了自带的authc过滤器,让未登录的请求统一返回401。MyFilter是用于过滤需要权限校验的请求。

import java.io.IOException;

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

import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.cmcc.hygcc.comm.dao.CommonDao;

/**
 * @Type LoginFilter.java
 * @Desc 用于自定义过滤器,过滤用户请求时是否是登录状态
 * @author Zero
 * @date 2017年2月6日 上午9:06:15
 * @version 
 */
public class LoginFilter extends AuthorizationFilter {
    @Autowired
    public CommonDao dao;

    @Override
    protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object arg2)
            throws Exception {
        Subject subject = getSubject(req, resp);
        if (null != subject.getPrincipals()) {
            return true;
        }
        return false;
    }

    /**
     * 会话超时或权限校验未通过的,统一返回401,由前端页面弹窗提示
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
            throws IOException {
        if (isAjax((HttpServletRequest) request)) {
            WebUtils.toHttp(response).sendError(401);
        } else {
            String unauthorizedUrl = getUnauthorizedUrl();
            if (StringUtils.hasText(unauthorizedUrl)) {
                WebUtils.issueRedirect(request, response, unauthorizedUrl);
            } else {
                WebUtils.toHttp(response).sendError(401);
            }
        }

        return false;
    }

    private boolean isAjax(HttpServletRequest request) {
        String header = request.getHeader("x-requested-with");
        if (null != header && "XMLHttpRequest".endsWith(header)) {
            return true;
        }
        return false;
    }
}

import java.io.IOException;
import java.util.Set;

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

import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.cmcc.hygcc.comm.dao.CommonDao;

/**
 * @Type MyFilter.java
 * @Desc 用于自定义过滤器,过滤用户请求是否被授权
 * @author Zero
 * @date 2017年2月6日 上午9:06:15
 * @version 
 */
public class MyFilter extends AuthorizationFilter {
    @Autowired
    public CommonDao dao;

    @SuppressWarnings("unchecked")
    @Override
    protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object arg2)
            throws Exception {
        HttpServletRequest request = (HttpServletRequest) req;
        //获取请求路径
        String path = request.getServletPath();
        Subject subject = getSubject(req, resp);
        if (null != subject.getPrincipals()) {
            //根据session中存放的用户权限,比对路径,如果拥有该权限则放行
            Set userPrivileges = (Set) request.getSession()
                    .getAttribute("USER_PRIVILEGES");
            if (null != userPrivileges && userPrivileges.contains(path)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 会话超时或权限校验未通过的,统一返回401,由前端页面弹窗提示
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
            throws IOException {
        if (isAjax((HttpServletRequest) request)) {
            WebUtils.toHttp(response).sendError(401);
        } else {
            String unauthorizedUrl = getUnauthorizedUrl();
            if (StringUtils.hasText(unauthorizedUrl)) {
                WebUtils.issueRedirect(request, response, unauthorizedUrl);
            } else {
                WebUtils.toHttp(response).sendError(401);
            }
        }

        return false;
    }

    private boolean isAjax(HttpServletRequest request) {
        String header = request.getHeader("x-requested-with");
        if (null != header && "XMLHttpRequest".endsWith(header)) {
            return true;
        }
        return false;
    }
}

主要的判断逻辑如下:当收到ajax请求,且该请求未授权时,返回错误码401。下面贴出前端ajax的处理代码:
$.ajaxSetup({
	cache:false,
        error : function(XMLHttpRequest, textStatus,errorThrown) { 
            switch (XMLHttpRequest.status){  
	            case(401): 
	            	tempAlert("会话超时或访问未授权,即将跳转到登录页!"); 
	            	setInterval("toLoginPage()",3000);
                break;
                default:  
                    tempAlert("网络连接已断开!"); 
            }
        }
});

由于前端有部分超链接,对超链接也做了ajax的封装,每个超链接通过onclick方法调用ajaxHref函数,代码如下。这样就可以实现不论前端页面是超链接或是ajax请求,在请求未授权时,页面都会统一弹出确认窗口,并自动跳转到登录页。
function ajaxHref(url){
			$.ajax({
				type : 'GET',
				url : url,
				async : false,
				success:function(){
					window.location.href=url;
				}
			});
		}



你可能感兴趣的:(springMVC+shiro的权限管理和异常统一处理)