反馈已提交

网络繁忙

Java防盗链在报表上面的应用

  • 文档创建者:文档助手1
  • 历史版本:44
  • 最近更新:Suki陈 于 2023-01-11
  • 1. 描述

    使用防盗链,来预防报表工程里的报表被直接访问或者被其他网站链接访问。

    注1:FineReport 11.0.12 版本新增 Referer 校验功能,可参考 Referer校验 进行配置,操作简单,无需处理复杂代码。

    注2:需先将 webroot 目录部署在外置 Tomcat 下才可生效(内置的设计器的 Tomcat 现在不读 web.xml 了)。

    注3:移动端访问也能起到防盗链作用。

    2. 原理

    浏览器中直接输入报表 URL 的时候,它的头文件是空的,因此,可以在访问的时候做两个判断:头文件是否为空以及以什么页面进行跳转,如果不符合跳到错误页面即可。

    1)什么是 Referer?

    这里的 Referer 指的是 HTTP 头部的一个字段,也称为 HTTP 来源地址(HTTP Referer),用来表示从哪儿链接到目前的网页,采用的格式是 URL。换句话说,借着 HTTP Referer 头部网页可以检查访客从哪里而来,这也常被用来对付伪造的跨网站请求。


    222

    2)什么是空 Referer,什么时候会出现空 Referer?

    首先,我们对空 Referer 的定义为,Referer 头部的内容为空,或者,一个 HTTP 请求中根本不包含 Referer 头部。

    那么什么时候 HTTP 请求会不包含 Referer 字段呢?根据 Referer 的定义,它的作用是指示一个请求是从哪里链接过来,那么当一个请求并不是由链接触发产生的,那么自然也就不需要指定这个请求的链接来源。

    比如,直接在浏览器的地址栏中输入一个资源的 URL 地址,那么这种请求是不会包含 Referer 字段的,因为这是一个“凭空产生”的 HTTP 请求,并不是从一个地方链接过去的。

    222

    那么在防盗链设置中,允许空 Referer 和不允许空 Referer 有什么区别?

    在防盗链中,如果允许包含空的 Referer,那么通过浏览器地址栏直接访问该资源 URL 是可以访问到的;

    但如果不允许包含空的 Referer,那么通过浏览器直接访问也是被禁止的。

    3. 操作步骤

    3.1 添加 class 文件

    编写一个类文件,用来判断头文件是否为空,代码如下:

    package com.fr.test;
    import java.io.IOException;
    import java.io.PrintWriter;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    public  class Dodo implements Filter {
        public void destroy() {
            // TODO Auto-generated method stub
        }
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse resp = (HttpServletResponse) response;
            String referer = req.getHeader("referer");
            //下面的IP地址是正常页面请求
            if(null != referer && (referer.trim().startsWith("http://localhost:8080")||referer.trim().startsWith("http://dev.fanruan.com/detail.html"))){
                System.out.println("正常页面请求"+referer);
                chain.doFilter(req, resp);
                //下面的就是出现不是正常页面请求的时候跳转
            }else{
                System.out.println("盗链"+referer);
                req.getRequestDispatcher("/LdapLogin.jsp").forward(req, resp);
            }
        }
        public void init(FilterConfig arg0) throws ServletException {
            // TODO Auto-generated method stub
        }
    }


    222

    注:条件语句说明如下

    null != referer 表示 referer 不为空。

    referer.trim().startsWith("http://localhost:8080") 指被访问的服务器地址,这句判断一定要有,因为正常访问状态下允许访问的链接跳转过来访问该链接开头的地址时,有两条申请,一个就是对该服务器的申请,如下图所示。此句表示允许访问以 http://localhost:8080 开头的链接。

    referer.trim().startsWith("http://dev.fanruan.com/detail.html") 此处网址 IP 或端口号不能与被访问的服务器地址相同,表示允许该链接跳转到以 localhost:8080 开头的链接地址来进行访问。

    将 Dodo.java 编译成 class 文件,并放在%TOMCAT_HOME%\webroot\WEB-INF\classes\com\fr\test目录下。

    222

    3.2 修改 web.xml 文件

    打开%TOMCAT_HOME%\webapps\webroot\WEB-INF下新建 web.xml 文件,配置一个过滤 filter,在出现 decision 的时候执行过滤,代码如下:

    222


    <?xml version="1.0" encoding="UTF-8"?>
    <web-app
       xmlns="http://java.sun.com/xml/ns/j2ee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
       version="2.4">
      <display-name>Template WebApp</display-name>
        <mime-mapping>
      <extension>msi</extension>
      <mime-type>application/x-msi</mime-type>
      </mime-mapping>
      <filter>
      <filter-name>AuthFilter</filter-name>
      <filter-class>com.fr.test.Dodo</filter-class>
    </filter>
      <filter-mapping>
      <filter-name>AuthFilter</filter-name>
      <url-pattern>/decision/*</url-pattern>
      </filter-mapping>
    </web-app>

    两步就可以搞定了,如果属于盗链,则跳转至上述的 LDAPLogin 错误页面,这里没有 LDAPLoign 页面,所以直接跳转 404。如果还想实现数据权限,则可以通过单点登录或者 Session 注入的方式。

    4. 效果测试

    准备两个 HTML 文件,放在外网 http://dev.fanruan.com/ 服务器文件夹下。

    注:在 IE 浏览器下,自带超链 FR.doHyperlinkByGet() 和 window.open() 方法跳转的链接没有 referer 属性,会造成了防盗链失败,可以使用表单 post 提交或者 a 标签来完成跳转。

    假设 http://dev.fanruan.com/detail.html 是正确的网址

    <html>
    <body>
    <a href='http://localhost:8080/webroot/decision/view/report?viewlet=test.cpt'>防盗链测试,正确的链接地址</p>地址:http://localhost:8080/webroot/decision/view/report?viewlet=test.cpt</a>
    </body>
    <html>

    假设 http://dev.fanruan.com 是盗链的网址

    <html>
    <body><a href='http://localhost:8080/webroot/decision/view/report?viewlet=test.cpt'>防盗链测试,错误的链接地址</p>地址:http://localhost:8080/webroot/decision/view/report?viewlet=test.cpt</a>
    </body>
    </html>

    4.1 情况一

    通过 http://dev.fanruan.com/detail.html 跳转,跳转链接正确,即 referer 不为空且正确

    222


    222

    4.2 情况二

    通过 http://dev.fanruan.com 跳转,跳转链接错误,即 referer 不为空且错误

    222


    222

    4.3 情况三

    直接访问 URL 地址,即 referer 为空

    222

    5. 注意事项

    在 IE 浏览器下,自带超链 FR.doHyperlinkByGet() 和 window.open() 方法跳转的链接没有 referer 属性,会造成了防盗链失败,可以使用表单 post 提交或者 a 标签来完成跳转。

    上述是以 a 标签跳转链接为例,准备的两个 html 文件,放在外网 www.finereporthelp.com 服务器文件夹下的。

    这里提供 post 提交方法,两个 HTML 文件内容为:

    <html>
      <head>  
      <title>FineReport Demo</title>  
      <meta http-equiv="Content-Type" content="text/html; charset=GBK" />  
      <script type="text/javascript">
        function post(URL, PARAMS,target) { var temp_form = document.createElement("form");    
                temp_form .action = URL;    
                temp_form .target = target;
                temp_form .method = "post";    
                temp_form .style.display = "none"; for (var x in PARAMS) { var opt = document.createElement("textarea");    
                    opt.name = x;    
                    opt.value = PARAMS[x];    
                    temp_form .appendChild(opt);    
                }    
                document.body.appendChild(temp_form);    
                temp_form .submit();   
            }
      </script>
      </head>  
      <body>
    <p>测试</p>  
    <input type="button" name="show" value="查询" onclick="post('/webroot/decision/view/report',{reportlet:'test.cpt',a:'111'},'_blank')"/>  
      </body>  
    </html>

    同样可以实现防盗链的效果。


    附件列表


    主题: 部署集成
    已经是第一篇
    已经是最后一篇
    • 有帮助
    • 没帮助
    • 只是浏览
    中文(简体)

    鼠标选中内容,快速反馈问题

    鼠标选中存在疑惑的内容,即可快速反馈问题,我们将会跟进处理。

    不再提示

    10s后关闭



    AI

    联系我们
    在线支持
    获取专业技术支持,快速帮助您解决问题
    工作日9:00-12:00,13:30-17:30在线
    页面反馈
    针对当前网页的建议、问题反馈
    售前咨询
    采购需求/获取报价/预约演示
    或拨打: 400-811-8890 转1
    qr
    热线电话
    咨询/故障救援热线:400-811-8890转2
    总裁办24H投诉:17312781526
    提交页面反馈
    仅适用于当前网页的意见收集,帆软产品问题请在 问答板块提问前往服务平台 获取技术支持