单独部署 url 安全之 ip 过滤器

 

润乾报表与用户的系统集成,一般有两种方案。一是集成到用户系统中。二是将润乾单独部署到一个应用下。

两种方案各有利弊:第一种方案对于安全性等方面可以统一管理,但是报表本身如果数据量大并发大造成的压力会直接影响用户自己的系统。第二种方案在报表服务器承受压力过大数据量过大的时候,不会影响到用户本身的系统,也就是说就算报表服务器压力饱和进入等待状态,用户的系统也可以正常的使用,众所周知润乾报表的调用一般直接通过 url 的方式进行调用,那么第二种方案中的 url 就无法被用户系统所控制,造成了一定的安全隐患。

下面就介绍几种解决此类问题的方案之中的一种:通过 ip 在过滤器中判断权限。

案例场景:

通过用户系统访问一张报表时,当然会带着一些用户信息或是其他参数传递过来。如果这时这个 url 被其他人复制或者记住,拿到其他客户机上直接访问,由于采用的是第二种方案,用户系统并不能控制,就会导致信息的泄漏。

解决思路:

这时我们可以采取从用户系统获取客户端 ip 然后拼成访问报表的参数,传递到报表服务器,然后在报表服务器中对该 ip 是否有权限打开这张报表进行判断,如果有权限继续访问,如果没有权限跳转到错误页面或者用户登陆页面等。

实现方法:

一、首先搭建报表服务器,这里以润乾自带 demo 为例。

正常访问报表 url 为:http://127.0.0.1:6868/demo/reportJsp/showReport.jsp?rpx=test.rpx

这个 url 就当做用户系统请求一张报表的 url,这时可以在这个 url 后加上登录用户系统的 ip,假设用户以 192.168.0.58 这个 ip 登陆的,那么 url 为:http://127.0.0.1:6868/demo/reportJsp/showReport.jsp?rpx=test.rpx&ipValue=192.168.0.58

二、写一个 filter

在 doFilter 中获取 url 中带的的参数以及客户端的 ip,然后进行比较


 public void  doFilter(ServletRequest request, ServletResponse response,

           FilterChain filterChain)  throws IOException, ServletException {

       // 过滤器获取客户端IP地址

       String ip = ((HttpServletRequest) request).getHeader("x-forwarded-for");

       if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

           ip = ((HttpServletRequest) request).getHeader("Proxy-Client-IP");

       }

      if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

           ip = ((HttpServletRequest) request).getHeader("WL-Proxy-Client-IP");

       }

      if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

           ip = ((HttpServletRequest) request).getHeader("HTTP\_CLIENT\_IP");

       }

      if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

           ip = ((HttpServletRequest) request).getHeader("HTTP\_X\_FORWARDED_FOR");

       }

      if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

           ip = request.getRemoteAddr();

       }

       // 根据获取的客户端IP,进行判断,返回相关结果为isValid=true

       boolean  isValid = false;

       String ipValue = request.getParameter(“ipValue”);

      if(ip.equals(ipValue)) {// 自行增加条件

           isValid =true;

       }

       // 如果满足条件允许登录,否则调准

      if(isValid) {

           request.setCharacterEncoding("GBK");

           filterChain.doFilter(request, response);

       }else{

           request.setCharacterEncoding("GBK");

           // 定向到Error页面,或者指定跳到登录界面

           request.getRequestDispatcher("/reportJsp/iperror.jsp").forward(

                  request, response);

       }

    }

三、在 web.xml 中加入 filter 配置

<filter>

    <filter-name>IpFilter</filter-name>

     <filter-class>com.runqian.filter.IpFilter</filter-class>

   </filter>

    <filter-mapping>

    <filter-name>IpFilter</filter-name>

      <url-pattern>/*</url-pattern>

     </filter-mapping>

然后重启服务,如果将 url 拷贝到其他 ip 的客户端访问,就会跳转到相应的错误页面。