1. 程式人生 > >web的越權訪問的處理(步驟詳解)

web的越權訪問的處理(步驟詳解)

使用者越權訪問的處理

一般來說,越權放問就好比你是非系統管理員使用者,卻偷偷的跑進了系統管理選單,僭越權利訪問裡面的資訊甚至修改其中的資料(不同級別的越權又稱垂直越權訪問),因此對資料的安全性造成極大的威脅,是故每家企業都有其方法來保證企業內部資料的安全性,也就是解決越權訪問的問題。

有關改業務處理主要考慮下面兩個方面:

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_URLSMENU_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.
    }

}