zoukankan      html  css  js  c++  java
  • Spring MVC 使用拦截器优雅地实现权限验证功能

    在上一篇 SpringAOP 实现功能权限校验功能 中虽然用AOP通过抛异常,请求转发等勉强地实现了权限验证功能,但感觉不是那么完美,应该用拦截器来实现才是最佳的,因为拦截器就是用来拦截请求的,在请求层面进行权限验证是最好的时机。

    假设下面的请求需要进行权限验证,在请求中通过参数params指定必须带有Helper.PARAM_FUNCTION_ID参数,这样拦截器通过判断是否带有该参数,如果带有则进行权限验证,否则不作处理。

    @RequestMapping(value = "/moduleAccess.do",params=Helper.PARAM_FUNCTION_ID, method = RequestMethod.POST, produces="text/html;charset=utf-8")
        @ResponseBody
        public String moduleAccess(String action,FrmModule module) {
            int rs = -1;
            try{
                if(Helper.F_ACTION_CREATE.equals(action)){
                    rs = moduleService.access(module,Helper.DB_ACTION_INSERT);
                    //module.setModuleid(rs);
                    module = moduleService.selectByPrimaryKey(rs);
                }else if(Helper.F_ACTION_EDIT.equals(action)){
                    rs = moduleService.access(module,Helper.DB_ACTION_UPDATE);
                    module = moduleService.selectByPrimaryKey(module.getModuleid());
                }else if(Helper.F_ACTION_REMOVE.equals(action)){
                    rs = moduleService.access(module,Helper.DB_ACTION_DELETE);
                }else{
                    return JSON.toJSONString(new Result(false,"请求参数错误:action"));
                }
            }catch(Exception e){
                e.printStackTrace();
                return JSON.toJSONString(new Result(false,"操作失败,出现异常,请联系管理员!"));
            }
            if(rs<0){
                return JSON.toJSONString(new Result(false,"操作失败,请联系管理员!"));
            }
            return  JSON.toJSONString(new Result(true,module));
        }

    那么对应的拦截器就直接用登录验证的那个拦截器即可,SecurityInterceptor

    package com.jykj.demo.filter;
    
    import java.io.PrintWriter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.alibaba.fastjson.JSON;
    import com.jykj.demo.entity.SysUser;
    import com.jykj.demo.service.SysUserRolePermService;
    import com.jykj.demo.util.Helper;
    import com.jykj.demo.util.Result;
    /**
     * 1.此拦截器用于拦截所有请求,用于登录权限验证
     * 2.拦截 带 moduleId 参数的请求,在渲染视图之前返回 模块权限值
     * @author Administrator
     *
     */
    public class SecurityInterceptor implements HandlerInterceptor{
        @Autowired
        SysUserRolePermService sysUserRolePermService;
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            System.out.println("SecurityInterceptor preHandle:"+request.getContextPath()+","+request.getRequestURI()+","+request.getMethod());
            HttpSession session = request.getSession();
            if (session.getAttribute(Helper.SESSION_USER) == null) {
                System.out.println("AuthorizationException:未登录!"+request.getMethod());
                if("POST".equalsIgnoreCase(request.getMethod())){
                    response.setContentType("text/html; charset=utf-8");  
                    PrintWriter out = response.getWriter();   
                    out.write(JSON.toJSONString(new Result(false,"未登录!")));
                    out.flush();
                    out.close();
                }else{
                    response.sendRedirect(request.getContextPath()+"/login"); 
                }
                return false;
            } else {
                Object obj = request.getParameter(Helper.PARAM_FUNCTION_ID);
                if(obj==null) return true;//没有带功能参数不需要验证
                int functionId = Integer.parseInt(obj.toString());
                String rs = sysUserRolePermService.permissionValidate(functionId);
                System.out.println("校验结果:"+rs);
                if(rs.trim().isEmpty()){
                    return true;//正常通过
                }else{
                    response.setContentType("text/html; charset=utf-8");  
                    PrintWriter out = response.getWriter();   
                    out.write(JSON.toJSONString(new Result(false,rs)));
                    out.flush();
                    out.close();
                    return false;
                }
            }
        }
        //模块权限值
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            /*
            Object obj = request.getParameter(Helper.PARAM_MODULE_ID);
            System.out.println(Helper.PARAM_MODULE_ID+":"+obj);
            if(obj == null) return;//如果没有moduleId 参数,否则什么都不做,否则返回模块权限值
            System.out.println("SecurityInterceptor postHandle:"+request.getContextPath()+","+request.getRequestURI()+","+request.getMethod());
            SysUser loginUser = (SysUser)request.getSession().getAttribute(Helper.SESSION_USER);
            int value = sysUserRolePermService.getModulePerm(loginUser.getUserid(),Integer.parseInt(obj.toString()));
            modelAndView.addObject(Helper.MVALUE,value);
            */
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
    
        }
    
    }
    

    拦截器配置不变

     <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/*"/>  <!-- 拦截/  /test  /login  等等单层结构的请求  --> 
                <mvc:mapping path="/**/*.aspx"/><!-- 拦截后缀为.aspx的请求 -->
                <mvc:mapping path="/**/*.do"/><!-- 拦截后缀为 .do的请求 -->
                <mvc:exclude-mapping path="/login"/>
                <mvc:exclude-mapping path="/signIn"/>
                <mvc:exclude-mapping path="/register"/>
                <bean class="com.jykj.demo.filter.SecurityInterceptor">
                </bean>
            </mvc:interceptor>
        </mvc:interceptors>

    这样即实现了对某个功能的权限校验的功能 
    客户端发送 /moduleAccess.do 请求,该请求带有参数Helper.PARAM_FUNCTION_ID,其值为某个功能的id 
    然后拦截器拦截该请求,判断出带有该参数,则对其进行权限校验,如果未通过,写response给客户端,格式是json的字符串,并返回false表示请求已由本拦截器处理了,不会往下执行(返回true表示正常往下执行)。这样就达到了权限验证的目的。这是相对更优雅的实现方式,最起码比上一篇讲的用AOP来实现更优雅。

    另外拦截器的postHandle方法是在控制器执行结束,页面渲染之前执行的,所以可以用来给页面添加或修改model属性。

  • 相关阅读:
    Bean复制
    java中的ConcurrentModificationException异常
    线程安全问题
    多线程等待唤醒机制之生产消费者模式
    JavaScript数据结构——队列的实现
    JavaScript数据结构——链表的实现
    JavaScript数据结构——栈的实现
    java中map集合的迭代
    SQLServer查询最近一天,三天,一周,一月,一季度方法
    细数网络上十七种安全威胁
  • 原文地址:https://www.cnblogs.com/yhtboke/p/5749071.html
Copyright © 2011-2022 走看看