首页 > 技术文章 > web的越权访问的处理(步骤详解)

b-code 2018-07-04 12:49 原文

通知:博客已搬家到CSDN地址为:
https://blog.csdn.net/hdp134793

用户越权访问的处理

一般来说,越权放问就好比你是非系统管理员用户,却偷偷的跑进了系统管理菜单,僭越权利访问里面的信息甚至修改其中的数据(不同级别的越权又称垂直越权访问),因此对数据的安全性造成极大的威胁,是故每家企业都有其方法来保证企业内部数据的安全性,也就是解决越权访问的问题。

有关改业务处理主要考虑下面两个方面:

url的越权访问和接口方法的越权访问

  1. 通过角色用户来判断是否越权访问

分下面几种情况来讨论:

  a.当没有用户登录的时候:

    只允许登录界面和一些js,css等非jsp/html的页面访问,这样算是越权

  b.当用户登录了之后:

    首先通过角色关系去数据库中查找他能够访问的页面,这样的话就可以针对能访问的做一个放行处理,非权限内的页面属于越权,这个时候拦截掉,可以直接让其跳转到登陆界面表示他越权了已经(自行处理越权后的操作)。

  2.具体实现流程

  a.统计好每个菜单url对应的接口方法和子页面访问路径(jsp或html等)

  b.将统计好的数据一一对应起来,存放在配置文件中或者数据库某个表中,这些数据随着业务的新增或者裁剪应有相关对应的维护,暂时以配置文件为例

  c.在登录模块中通过登录的用户角色查找它能够访问的菜单URL(写一个接口方法),存放在一个静态公有list变量中,如下定义:

public static List<String> MENU_URLS = new ArrayList<>();

将查询返回过来的url集合塞给MENU_URLS

  d,定义一个静态公有Properties变量,用来存放配置文件中的键值对,如下定义:

public static Properties MENU_INTERFACE = null;

然后对其进行读取配置文件并赋值

String url = request.getSession().getServletContext().getRealPath("/WEB-INF/classes/porturl.properties");
File file = new File(url);
    try {
        MENU_INTERFACE = new Properties();
        FileInputStream inStream = new FileInputStream(file);
        MENU_INTERFACE.load(inStream);
        } catch (Exception e) {
            System.out.println(e);
}

  e.SpringMVC拦截器,判断session中用户是否过期,在doFilter 方法里匹配,只要js,css,pdf,png,jpg等文件可放行,在里面判断用户是否登录,没有登录的话只要是非登录页面的页面,统一视为越权访问。如果是已经登录的用户,我们可以取到登录后的MENU_URLS  MENU_INTERFACE 的信息,可以做如下判断:

如果访问的路径checkURL和MENU_URLS 中的任意子串能匹配的上的话说明是可以访问的,这种情况放行,否则拦截下来跳转登录,记录越权访问信息;

在上面的情况下,还会存在一种情况,当访问的路径是子页面的时候,这个时候需要去匹配,能匹配上的可以放行,这个需要通过checkURL去配置文件中找到对应的父URL,然后再进行匹配MENU_URLS这个里面的父URL是唯一的,配置文件中一(父)对多(子)。

接口访问的也是同样的道理。

其中放行方法:

//正常访问,直接放行
filterChain.doFilter(servletRequest, servletResponse);
return;
//初始化printWriterURL
String printWriterURL="<script>window.location.href='"+httpRequest.getContextPath()+ "/jsps/login/login.jsp';</script>";
//其他jsp的时候算是越权访问
logger.info("用户越权访问!!!!" + url);
PrintWriter p = httpResponse.getWriter();
p.write(printWriterURL);
p.flush();
p.close();
return;

这样就大功告成,具体代码细节如下所示:

public class SystemFilter implements Filter {
    private static Logger logger = Logger.getLogger(SystemFilter.class);

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        HttpSession session = httpRequest.getSession(true);
        String url = httpRequest.getRequestURI();
        String printWriterURL = "<script>window.location.href='" + httpRequest.getContextPath() + "/jsps/login/login.jsp';</script>";
        String checkURL = url;
        if(checkURL.endsWith("/")){
            checkURL = checkURL.substring(0, checkURL.length()-1);
            if(checkURL.split("/").length == 2){
                PrintWriter p = httpResponse.getWriter();
                p.write(printWriterURL);
                p.flush();
                p.close();
                return;
            }
        }
        Object object = session.getAttribute("user");
        User user = object == null ? null : (User) object;
        boolean isAjaxRequest = false;
        if (!StringUtils.isBlank(httpRequest.getHeader("x-requested-with"))
                && httpRequest.getHeader("x-requested-with").equals("XMLHttpRequest")) {
            isAjaxRequest = true;
        }
        StringBuffer server = httpRequest.getRequestURL();
        if (server.toString().contains(".css") || server.toString().contains(".jsp")
                || (server.toString().contains(".js") && !server.toString().contains(".jsp"))
                || server.toString().contains(".png") || server.toString().contains(".jpg") || server.toString().contains(".gif") || server.toString().contains(".svg")
                || server.toString().contains(".so") || server.toString().contains(".woff") 
                || server.toString().contains(".ttf") 
                || server.toString().endsWith("/downPDF")         // 下载放行
                || server.toString().contains("/websocket")     // 推送放行
        ){
            if(user ==null && server.toString().contains(".jsp")){
                if(server.toString().contains("index.jsp")){
                    logger.info("!!!用户未登录且使用index.jsp页面:" + url);
                    PrintWriter p = httpResponse.getWriter();
                    p.write(printWriterURL);
                    p.flush();
                    p.close();
                    return;
                }else if(server.toString().contains("login.jsp")){
                    //当访问的是login.jsp的时候放行
                    filterChain.doFilter(servletRequest, servletResponse);
                    return;
                }else{
                    //其他jsp的时候算是越权访问
                    logger.info("用户越权访问!!!!" + url);
                    PrintWriter p = httpResponse.getWriter();
                    p.write(printWriterURL);
                    p.flush();
                    p.close();
                    return;
                }
            }else if(user !=null && server.toString().contains(".jsp") && !(server.toString().contains("login.jsp"))){
                Boolean ISURL = false;
                //获取访问url的字符串
                int urllen = checkURL.split("/").length;
                String checkurl = "";
                for(int i=2;i<urllen;i++){
                    if(i<urllen-1){
                        checkurl+=checkURL.split("/")[i]+"/";
                    }else{
                        checkurl+=checkURL.split("/")[i];
                    }
                }
                c:for(int j=0;j<LoginService.MENU_URLS.size();j++){
                    //获取角色用户对应二级菜单的URL
                    String _orUrls = LoginService.MENU_URLS.get(j);
                    if(_orUrls.equals(checkurl)){
                        System.out.println("符合条件的:"+checkurl);
                        ISURL = true;
                        break c;
                    }
                }
                //当上一个判断时不能访问考虑第二种情况
                if(!ISURL){
                    //通过二级菜单读取配置文件中对应的子url,防止空指针异常
                    String purls = LoginService.MENU_INTERFACE.get(checkurl)==null?"":LoginService.MENU_INTERFACE.get(checkurl).toString();
                    d:for(int j=0;j<LoginService.MENU_URLS.size();j++){
                        String _orUrls = LoginService.MENU_URLS.get(j);
                        //获取角色用户对应二级菜单的URL和通过访问路径去查配置文件时候存在吻合则放行
                        if(_orUrls.equals(purls)){
                            System.out.println("符合条件的:"+purls);
                            ISURL = true;
                            break d;
                        }
                    }
                }
                
                if(!ISURL){
                    //越权访问
                    String msg = "ip=" + user.getIpaddr() + "&name=" + user.getUsername();
                    logger.info("!!!越权访问:" + url + ";用户信息:" + msg);
                    printWriterURL = "<script>window.location.href='" + httpRequest.getContextPath() + "/jsps/login/login.jsp?" + msg + "';</script>";
                }else{
                    System.out.println("========>"+LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]));
                    //正常访问,直接放行
                    filterChain.doFilter(servletRequest, servletResponse);
                    return;
                }
                PrintWriter p = httpResponse.getWriter();
                p.write(printWriterURL);
                p.flush();
                p.close();
                return;
            }
            // 如果发现是css或者js文件,直接放行
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        
        if (!isAjaxRequest) {
            if (user != null && (server.toString().contains("index.jsp") || server.toString().contains("login.jsp"))) {
                // 如果发现是css或者js文件,直接放行
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            } else {
                if(user != null){
                    System.out.println("-----------1-----------"+checkURL);
                    if(LoginService.MENU_INTERFACE != null && LoginService.MENU_INTERFACE.size() != 0 
                            && LoginService.MENU_URLS != null && LoginService.MENU_URLS.size() != 0 ){
                        if(checkURL.split("/").length == 4){
                            System.out.println("-----------2-----------"+LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]));
//                            if(LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]) == null){
//                                // 如果发现是css或者js文件,直接放行
//                                filterChain.doFilter(servletRequest, servletResponse);
//                                return;
//                            }
                            Boolean hasIn = false;
                            if(null != LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3])){
                                String[] urls = LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]).toString().split(",");
                                // jsp/pages/configmgt/device/deviceList.jsp,jsp/pages/configmgt/systemmgt/systemmgtList.jsp
                                a:for(int i=0;i<urls.length;i++){
                                    String _url = urls[i];
                                    for(int j=0;j<LoginService.MENU_URLS.size();j++){
                                        String _orUrls = LoginService.MENU_URLS.get(j);
                                        if(_orUrls.equals(_url)){
                                            System.out.println("符合条件的:"+_url);
                                            hasIn = true;
                                            break a;
                                        }
                                    }
                                }
                                
                            }
                            if(!hasIn){
                                //越权访问
                                String msg = "ip=" + user.getIpaddr() + "&name=" + user.getUsername();
                                logger.info("!!!越权访问:" + url + ";用户信息:" + msg);
                                printWriterURL = "<script>window.location.href='" + httpRequest.getContextPath() + "/jsps/login/login.jsp?" + msg + "';</script>";
                            }else{
                                System.out.println("========>"+LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]));
                                //正常访问,直接放行
                                filterChain.doFilter(servletRequest, servletResponse);
                                return;
                            }
                        }
                    }
                    
                    
                }
                PrintWriter p = httpResponse.getWriter();
                p.write(printWriterURL);
                p.flush();
                p.close();
                return;
            }
        }
        if (url.toString().contains(".jsp")) {
            logger.info(httpRequest.getSession().getServletContext().getRealPath("/") + "-------");
            logger.info("拦截器放行地址:-------------------" + url);
        }
        filterChain.doFilter(servletRequest, servletResponse);
        return;
    }

    /**
     * 判断是否为Ajax请求
     * 
     * @param request
     *            HttpServletRequest
     * @return 是true, 否false
     */
    public static boolean isAjaxRequest(HttpServletRequest request) {
        return request.getRequestURI().startsWith("/api");
        // String requestType = request.getHeader("X-Requested-With");
        // return requestType != null && requestType.equals("XMLHttpRequest");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
        // To change body of implemented methods use File | Settings | File
        // Templates.
    }

}

 

 

 

 

推荐阅读