zoukankan      html  css  js  c++  java
  • 权限控制之判断与重定向

    基于spring框架的监听器开发而成

    package com.zyh.system;
    
    import java.io.PrintWriter;
    import java.net.URLEncoder;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.zyh.domain.mainCode.PermissionsResource;
    import com.zyh.domain.mainCode.RolePermission;
    import com.zyh.domain.mainCode.Roles;
    import com.zyh.domain.mainCode.User;
    import com.zyh.domain.mainCode.UserLogin;
    import com.zyh.service.mainCode.IPermissionsResourceService;
    import com.zyh.service.mainCode.IRolePermissionService;
    import com.zyh.service.mainCode.IUserService;
    import com.zyh.util.HtmlUtils;
    import com.zyh.util.JsonUtils;
    import com.zyh.util.SessionUtils;
    import com.zyh.vo.base.JsonResult;
    
    /**
     * Spring MVC 拦截器 首先要在Spring MVC的配置文件xml中 添加配置拦截器
     *
     * <mvc:interceptors> <!-- 日志拦截器 --> <mvc:interceptor> <mvc:mapping path="/**"
     * /> <mvc:exclude-mapping path="/static/**" />
     *
     * 有两种方式一种是HandlerInterceptor接口 还有一种是WebRequestInterceptor接口
     * 但是我们今天使用的是HandlerInterceptor接口
     *
     * 还有一种是HandlerInterceptorAdapter ??? 区别是什么 ??? 尚未可知
     * 这种通过抽象类继承的方式使用的方式使用范例在com.hfepc.interceptor.LoginInterceptor 和
     * com.hfepc.interceptor.PermissionInterceptor
     *
     * 区别是: 1、HandlerInterceptor 是接口 通过实现接口完成相应的功能 import
     * org.springframework.web.servlet.HandlerInterceptor;
     *
     * 2、HandlerInterceptorAdapter 是抽象类 通过实现子类完成相应的功能 import
     * org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
     *
     * 关注一个事物的本质的时候,用抽象类; 关注一个操作的时候,用接口
     *
     * @author 1101399
     * @CreateDate: 2018-1-4 上午9:45:25
     */
    public class AllInterceptor implements HandlerInterceptor {
    
        static Logger log = LoggerFactory.getLogger(AllInterceptor.class);
    
        @Autowired
        private IUserService userService;
        @Autowired
        private IRolePermissionService rolePermissionService;
        @Autowired
        private IPermissionsResourceService permissionsResourceService;
    
        /**
         * preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,
         * SpringMVC中的Interceptor拦截器是链式的,可以同时存在多个Interceptor,
         * 然后SpringMVC会根据声明的前后顺序一个接一个的执行,
         * 而且所有的Interceptor中的preHandle方法都会在Controller方法调用之前调用。
         * SpringMVC的这种Interceptor链式结构也是可以进行中断的,
         * 这种中断方式是令preHandle的返回值为false,当preHandle的返回值为false的时候整个请求就结束了。
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                Object handler) throws Exception {
            // TODO Auto-generated method stub
            log.info("拦截器拦截成功");
            boolean success = false;
    
            String uri = request.getRequestURI(); // 输出:/kanban/login
            String contextPath = request.getContextPath(); // 输出:/kanban
            uri = uri.substring(contextPath.length() + 1); // 输出:login
    
        /*    // 例如:/kanban/login
            String requestURL = request.getRequestURI(); // 输出:/kanban/login
            String contextPath = request.getContextPath(); // 输出:/kanban
            requestURL = requestURL.substring(contextPath.length() + 1); // 输出:login
    */
            /**
             * 判断用户登录信息是否存在 - 否的话返回登录界面 - 是的话继续进行下一步操作
             */
            UserLogin userLogin = SessionUtils.getLoginUser();
            if (null == userLogin) {
                log.debug("未登录&登录超时!");
                // 界面返回login界面
                String message = "未登录&登录超时!";
                // 判断一下是否有URL传入有点话设法使登录之后直接调转道相应的URL位置中去
                PrintWriter out = response.getWriter();
                if (HtmlUtils.isAjaxRequest(request)) {// 判断是否是ajax方法
                    response.setContentType("application/json;charset=UTF-8");
                    out.print(JsonUtils.toString(new JsonResult<String>(false, "登录超时(或未登录),请重新登录!")));
                } else {
                    String path = request.getContextPath();
                    String basePath = request.getScheme() + "://" + request.getServerName() + ":"
                            + request.getServerPort() + path + "/";
                    String url = basePath + "unlogin.jsp?redirectUrl=" + URLEncoder.encode(uri, "UTF-8");
                    out.println("<script type="text/javascript">");
                    out.println("window.open('" + url + "','_top')");
                    out.println("</script>");
                }
                out.flush();
                return false;
            }
    
            // 判断过滤部分 - 通过URL判断实现对非法访问的拦截
            // 权限过滤
    
            User user = userService.findByUserLogin(userLogin);
            Roles temRoles = user.getRoles();//用户角色信息
            RolePermission temRoleper = rolePermissionService.findByRolesId(temRoles.getRoleId());
            List<PermissionsResource> temPerResourceList = permissionsResourceService.findByPermissionId(temRoleper.getPermissions().getPermissionId());
    
            // 添加用户拥有的URL资源
            List<String> URIList = new ArrayList<String>();
            for(int i = 0;i < temPerResourceList.size(); i++){
                PermissionsResource func = temPerResourceList.get(i);
                URIList.add(func.getResources().getResources());
            }
    
           // HttpSession session = pageContext.getSession();
           // List<String> URIList = (List<String>) session.getAttribute(Constants.SESSION_URI_LIST);
    
            if (URIList == null || URIList.isEmpty()) {
                success = false;
            } else {
                for (int i = 0; i < URIList.size(); i++) {
                    String regexURL = URIList.get(i);
    
                    if (regexURL.equals(uri)) {
                        success = true;
                        break;
                    }
                    /*
                    // 使用正则表达式进行匹配(数据库中已设置的url本身就是个正则表达式)
                    Pattern pattern = Pattern.compile(regexURL);
                      Matcher matcher = pattern.matcher(uri); if
                      (matcher.matches()) { success = true; break; }
                     */
                }
            }
    
    
            if (success)
                return true;
            else
                if (HtmlUtils.isAjaxRequest(request)) {//判断是否是ajax 方法
                    response.setContentType("application/json;charset=UTF-8");
                    PrintWriter out = response.getWriter();
                    JsonResult result = new JsonResult();
                    result.setStatus(false);
                    result.setMessage("对不起,您没有访问操作的权限!
    请求地址:" + uri);
                    String json = JsonUtils.toString(result);
                    out.print(json);
                } else {
                    // 若是普通请求,则跳转至权限不足提示的也没
                    String path = request.getContextPath();
                    String basePath = request.getScheme() + "://" + request.getServerName() + ":"
                            + request.getServerPort() + path + "/";
                /**
                 * 使用指定的重定向位置URL向客户端发送临时重定向响应,并清除缓冲区。缓冲区将被这个方法设置的数据替换。
                 * 调用此方法将状态码设置为SC_FOUND 302(找到)。这个方法可以接受相对的URL;
                 * servlet容器在把响应发送给客户端之前
                 * ,必须将相对URL转换为绝对URL。如果该位置是相对的而没有前导'/',则容器将其解释为相对于当前请求URI
                 * 。如果该位置与前导“/”相对,则容器将其解释为相对于servlet容器根。
                 *
                 * 如果响应已被提交,则此方法将引发IllegalStateException。在使用这个方法之后,应该认为响应是被提交的,
                 * 不应该被写入。
                 */
                    response.sendRedirect(basePath + "noRight.jsp?uri=" + uri);
                }
                return false;
        }
    
        /**
         * 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。
         * postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之 后, 也就是在Controller的方法调用之后执行,
         * 但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操作。
         * 这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用,
         * 这跟Struts2里面的拦截器的执行过程有点像,
         * 只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法,
         * Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor或者是调用action,
         * 然后要在Interceptor之前调用的内容都写在调用invoke之前,要在Interceptor之后调用的内容都写在调用invoke方法之后。
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response,
                Object handler, ModelAndView modelAndView) throws Exception {
            // TODO Auto-generated method stub
            log.info("拦截器拦截成功------------- postHandle:DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处");
        }
    
        /**
         * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。
         * 该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行, 这个方法的主要作用是用于清理资源的,
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                Object handler, Exception ex) throws Exception {
            // TODO Auto-generated method stub
            log.info("拦截器拦截成功++++++++++++++ afterCompletion:清理资源");
        }
    }
    

      还有一种方式是继承相应的父类来实现,而我的方式是通过实现接口来实现的。

    痛苦预示着超脱
  • 相关阅读:
    Mybatis 与 spring mvc
    Extjs 表格横坐标显示问题
    Extjs 图片的自动缩放
    C# Winform 界面中各控件随着窗口大小变化
    spring 连接各种数据源的配置(转载)
    <转>(C#)WinForm窗体间传值
    java stack 底层详细
    java hashmap 底层详细
    java LinkedList 底层详细
    java ArrayList 底层详细
  • 原文地址:https://www.cnblogs.com/supperlhg/p/8390973.html
Copyright © 2011-2022 走看看