美文网首页java
SpringMVC 拦截器实现权限统一校验

SpringMVC 拦截器实现权限统一校验

作者: 二妹是只猫 | 来源:发表于2019-03-12 11:42 被阅读0次
    在dispatcher-servlet.xml中添加拦截器:
    <mvc:interceptors>
            <!-- 定义在这里的,所有的都会拦截-->
            <mvc:interceptor>
                <mvc:mapping path="/manage/**"/>
                <!--不需要拦截的接口-->
                <!--<mvc:exclude-mapping path="/manage/user/login.do"/>-->
                <bean class="com.mmall.controller.common.interceptor.AuthorityInterceptor" />
            </mvc:interceptor>
        </mvc:interceptors>
    

    拦截的目录的规则

    /       从根目录
    /*      拦截当前目录一级的
    /**     拦截当前目录和它的子目录
    
    新建拦截器实现HandlerInterceptor接口:
    public class AuthorityInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
        }
    }
    

    拦截器的执行顺序preHandle->controller-> postHandle-> afterCompletion, preHandle返回false将不在执行后面的方法。

    preHandle中实现拦截逻辑:
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            HandlerMethod handlerMethod = (HandlerMethod)handler;
    
            String methodName = handlerMethod.getMethod().getName();
            String className = handlerMethod.getBean().getClass().getSimpleName();
    
            //解析参数,具体的参数key以及value是什么,我们打印日志
            StringBuffer requestParamBuffer = new StringBuffer();
            Map paramMap = request.getParameterMap();
            Iterator it = paramMap.entrySet().iterator();
            while (it.hasNext()){
                Map.Entry entry = (Map.Entry) it.next();
                String mapKey = (String) entry.getKey();
                String mapValue = StringUtils.EMPTY;
    
                //request这个参数的map,里面的value返回的是一个String[]
                Object object = entry.getValue();
                if (object instanceof String[]){
                    String[] strs = (String[]) object;
                    mapValue = Arrays.toString(strs);
                }
    
                requestParamBuffer.append(mapKey).append("=").append(mapValue);
            }
    
            log.info("权限拦截器拦截到请求,className:{},methodName:{},param:{}",className,methodName,requestParamBuffer.toString());
    
            User user = null;
    
            String loginToken = CookieUtil.readLoginToken(request);
            if(org.apache.commons.lang.StringUtils.isNotEmpty(loginToken)){
                String userJsonStr = RedisShardedPoolUtil.get(loginToken);
                user = JsonUtil.string2Obj(userJsonStr,User.class);
            }
    
            //以下就是项目中的逻辑代码,可根据项目的需求灵活改变
            if(user==null || user.getRole()== Const.Role.ROLE_CUSTOMER){
                response.reset();
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json;charset=UTF-8");
    
                PrintWriter out = response.getWriter();
                //上传由于富文本的控件要求,要特殊处理返回值,这里面区分是否登录以及是否有权限
                if(user == null){
                    if(org.apache.commons.lang.StringUtils.equals(className,"ProductManageController") && org.apache.commons.lang.StringUtils.equals(methodName,"richtextImgUpload")){
                        Map resultMap = Maps.newHashMap();
                        resultMap.put("success",false);
                        resultMap.put("msg","请登录管理员");
                        out.print(JsonUtil.obj2String(resultMap));
                    }else{
                        out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("拦截器拦截,用户未登录")));
                    }
                }else{
                    if(org.apache.commons.lang.StringUtils.equals(className,"ProductManageController") && org.apache.commons.lang.StringUtils.equals(methodName,"richtextImgUpload")){
                        Map resultMap = Maps.newHashMap();
                        resultMap.put("success",false);
                        resultMap.put("msg","无权限操作");
                        out.print(JsonUtil.obj2String(resultMap));
                    }else{
                        out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("拦截器拦截,用户无权限操作")));
                    }
                }
                out.flush();
                out.close();//geelynote 这里要关闭
    
                return false;
    
            }
            return true;
        }
    
    • 在拦截器中排除一些特殊的接口有两种方法:
      1.在dispatcher-servlet.xml中添加<mvc:exclude-mapping path=""/>:
    <mvc:interceptors>
            <!-- 定义在这里的,所有的都会拦截-->
            <mvc:interceptor>
                <mvc:mapping path="/manage/**"/>
                <!--不需要拦截的接口-->
                <mvc:exclude-mapping path="/manage/user/login.do"/>
                <bean class="com.mmall.controller.common.interceptor.AuthorityInterceptor" />
            </mvc:interceptor>
        </mvc:interceptors>
    

    2.通过preHandle中的handler对象获取类名、方法来进行逻辑判断:

    String methodName = handlerMethod.getMethod().getName();
    String className = handlerMethod.getBean().getClass().getSimpleName();
    
    • 通过HttpServletRequest获取请求参数,进行逻辑处理:
    StringBuffer requestParamBuffer = new StringBuffer();
    Map paramMap = request.getParameterMap();
    Iterator it = paramMap.entrySet().iterator();
    while (it.hasNext()){
                Map.Entry entry = (Map.Entry)it.next();
                String mapKey = (String)entry.getKey();
                String mapValue = StringUtils.EMPTY;
                //request这个参数的map,里面的value返回的是一个String[]
                Object obj = entry.getValue();
                if(obj instanceof String[]){
                    String[] strs = (String[])obj;
                    mapValue = Arrays.toString(strs);
                }
                requestParamBuffer.append(mapKey).append("=").append(mapValue);
     }
    

    需要注意的是HttpServletRequest获取到的参数是map需要处理后使用。

    • 如果进行了拦截将不在调用contoller中的方法,而preHandle返回的是布尔类型,所以需要对返回进行处理:
        if(user == null || (user.getRole().intValue() != Const.Role.ROLE_ADMIN)){
                //返回false.即不会调用controller里的方法
                response.reset();//geelynote 这里要添加reset,否则报异常 getWriter() has already been called for this response.
                response.setCharacterEncoding("UTF-8");//geelynote 这里要设置编码,否则会乱码
                response.setContentType("application/json;charset=UTF-8");//geelynote 这里要设置返回值的类型,因为全部是json接口。
    
                PrintWriter out = response.getWriter();
                Map resultMap = Maps.newHashMap();
                resultMap.put("status",1);
                if(user == null){
                        resultMap.put("msg","请登录管理员");
                }else{
                        resultMap.put("msg","无权限操作");
                }
                out.print(JsonUtil.obj2String(resultMap));
                out.flush();
                out.close();//geelynote 这里要关闭
    
                return false;
            }
    
    接口请求效果

    相关文章

      网友评论

        本文标题:SpringMVC 拦截器实现权限统一校验

        本文链接:https://www.haomeiwen.com/subject/pdjgpqtx.html