报表管理软件FineReport中模板权限的控制示例

2025-10-22 19:19:52

1、前提准备

报表工程:如直接使用内置Jetty服务器中的报表工程WebReport,端口为8075;

用户系统:如用户工程(在PFDemo目录)发布于Tomcat服务器,端口为8080;

PFDemo下有文件login.html(用户的登陆界面)、index.jsp(登陆后的主界面)、report.jsp(对报表请求进行签名,将签名信息加入请求中转发给报表工程)。注:下面有对应文件的完整代码。

配置好报表端的身份验证>并与用户系统实现单点登录:

如该例我们使用数据集验证,用户-密码服务器数据集定义如下:

报表管理软件FineReport中模板权限的控制示例

2、登陆平台系统http://localhost:8075/WebReport/ReportServer?op=fr_platform,点击管理系统>用户管理>设置,认证方式使用默认的平台内置认证,配置用户同步数据集,如下图:

报表管理软件FineReport中模板权限的控制示例

3、修改用户登录界面login.html,实现单点登录,代码如下:

<html> 

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

<script type="text/javascript">

  function loginFR() {

     var username =document.getElementById("username").value;   

     var password =document.getElementById("password").value;

     var scr = document.createElement("iframe");

     scr.src = "http://localhost:8075/WebReport/ReportServer?op=touchpf&__redirect__=false&username=" + username + "&password=" + password + "&_t=" + (Math.random() * 10000) ;

     if (scr.attachEvent){

  scr.attachEvent("onload", function(){

      var f = document.getElementById("loginForm");

        f.submit();

  });

} else {

  scr.onload = function(){

   var f = document.getElementById("loginForm");

    f.submit();

  };

}

     

     document.getElementsByTagName("head")[0].appendChild(scr);

  }

  </script>

<body>

<form id="loginForm" name="loginForm" method="post" action="/PFDemo/index.jsp">

<table>

<tbody>

<tr class="prop">

<td class="name"><label>

Username</label></td>

<td class="value"><input id="username" type="text" name="username" value="A" /></td>

</tr>

<tr class="prop">

<td class="name"><label>

Password</label></td>

<td class="value"><input id="password" type="password" name="password" value="" /></td>

</tr>

</tbody>

</table>

</div></div></div>

<div class="actionButtons">

<input id="lalala" type="button" name="lalala" onclick="loginFR();" value ="登录"/>

<input id="sub" type="submit" name="sub" value="" style="display:none;"/>

</div>

</form>

</body>

</html>

4、拷贝jar包

下载fr-pfh-java-7.0.jar包,选择权限集成-JAVA资源>fr-pfh-java-7.0.jar,拷贝至报表工程WebReport\WEB-INF\lib及用户系统PFDemo\WEB-INF\lib下(注意:报表工程与用户系统下都要有);

将报表工程WebReport\WEB-INF\lib下的fr-third-7.0.jar包拷贝至用户系统PFDemo\WEB-INF\lib下。

5、用户系统中添加一个web接口给报表工程提供公钥

这个接口是一个地址,比如在用户系统中注册一个servlet,访问这个servlet来获得公钥,http://localhost:8080/PFDemo/DemoServer?cmd=getkey:

在用户系统的PFDemo\WEB-INF\web.xml中添加一个servlet:

<web-app> 

  <display-name>Demo WebApp</display-name>

  <servlet>

    <servlet-name>DemoServer</servlet-name>

    <servlet-class>demo.DemoServlet</servlet-class>

    <load-on-startup>0</load-on-startup>

  </servlet>

  <servlet-mapping>

    <servlet-name>DemoServer</servlet-name>

    <url-pattern>/DemoServer</url-pattern>

  </servlet-mapping>

</web-app>

6、DemoServer这个servlet所对应的类为demo.DemoServlet,代码如下:

package demo;

import java.io.IOException;

import java.io.PrintWriter;

import java.math.BigInteger;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.fr.pf.java.FRPrivilegeFilterHelper;

public class DemoServlet extends HttpServlet {

    public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {

    doPost(req, res);

    }

    

    /**

     * 这里只是示例,就简单处理,不做分层了

     */

    public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {

    String cmd = req.getParameter("cmd");

    if ("getkey".equals(cmd)) {

    dealWithKey(req, res);

    }

    }

    

    private void dealWithKey(HttpServletRequest req, HttpServletResponse res) throws IOException {

    PrintWriter writer = new PrintWriter(res.getOutputStream());

    try {

    // 获得公钥的两个参数,传回

BigInteger modulus = FRPrivilegeFilterHelper.getPublicKeyModulus();

BigInteger exponent = FRPrivilegeFilterHelper.getPublicKeyExponent();

writer.write(modulus.toString() + "&" + exponent.toString());

} catch (Exception e) {

e.printStackTrace();

writer.write("error");

}

writer.flush();

writer.close();

    }

}

编译后的类保存在PFDemo\WEB-INF\classes\demo\DemoServlet.class。

7、报表工程中获取用户系统的公钥

登陆管理平台,选择权限配置>详细权限配置;

数字签名密钥地址为http://localhost:8080/PFDemo/DemoServer?cmd=getkey,点击提交:

报表管理软件FineReport中模板权限的控制示例

8、用户系统发送报表请求加入数字签名信息

如最上图中登陆后的主界面为index.jsp,代码如下:

<%@page contentType="text/html;charset=gbk" pageEncoding="gbk"%>

<%

String username = request.getParameter("username");

String password = request.getParameter("password");

// 下面是用户系统对登陆用户名和密码的验证,以下用最简单的代码做示例

if ("A".equals(username) && "123".equals(password)) {

    request.getSession().setAttribute("username", "A");

} else if ("B".equals(username) && "123".equals(password)) {

    request.getSession().setAttribute("username", "B");

} else {

request.getSession().setAttribute("username", "");

}

%>

<html>

<head>

   <title>Privilege Demo</title>

<script type="text/javascript">

function viewReport(report) {

var f = document.getElementById("frame");

f.src = "/PFDemo/report.jsp?report=" + report;

}

</script>

</head>

<body bgcolor="#FFFFFF">

<table style="width:1018px;" border="2">

<colgroup>

<col width="150px;"/>

<col/>

</colgroup>

    <tr style="height:30px;">

    <td style="font-size:24pt;background-color:blue;color:#EFEFEF;" colSpan="2">

    Privilege Demo

    <span style="margin-left:500px;">Current user:</span>

    <%=username%>

    </td>

    </tr>

    <tr style="height:730px;">

    <td style="vertical-align:top;">

    <% if ("A".equals(request.getSession().getAttribute("username"))) {

    %>

    <ul>

    <li style="cursor:pointer;color:blue;" onclick="javascript:viewReport('GettingStarted.cpt');">

    Report1(A,B)

    </li>

    <li style="cursor:pointer;color:blue;" onclick="javascript:viewReport('doc/Primary/CrossReport/Cross.cpt');">

    Report2(A)

    </li>

    </ul>

    <%

    } else if ("B".equals(request.getSession().getAttribute("username"))) {

    %>

    <ul>

    <li style="cursor:pointer;" onclick="javascript:viewReport('GettingStarted.cpt');">

    Report1(A,B)

    </li>

    </ul>

    <%

    }

    %>

    </td>

    <td>

     <iframe id="frame" name="frame

    </td>

    </tr>

  </table>

</body>

</html>

当点击左边报表节点时,触发viewReport这个js方法,通过iframe执行report.jsp文件,并传递请求查看的报表名字。

9、在report.jsp中利用fr-pfh-java-7.0.jar提供的接口,对需要访问的报表路径、报表浏览形式(op)、当前用户名与当前系统时间进行数字签名,得到签名信息,并将签名信息加入请求中转发给报表工程,代码如下:

<%@page contentType="text/html;charset=gbk" import="com.fr.pf.java.*" pageEncoding="gbk"%>

<%

String reportPath = request.getParameter("report");   // 获得需要访问的报表路径,即我方reportlet参数

String username = (String)request.getSession().getAttribute("username");  // 获取当前用户名

String op = "page";  // 默认分页预览时,null即可

long curtime = System.currentTimeMillis();  // 获取当前时间

String signInfo = FRPrivilegeFilterHelper.sign(reportPath, op, username, curtime);   // 将上述获得的四个要素传入,获得相关的数字签名信息

String path = "http://localhost:8075/WebReport/ReportServer?reportlet=" + reportPath + "&op=" + op 

              + "&" + FRPrivilegeFilterHelper.FR_DIGITALSIGNATURE_CURRENT_TIME + "=" + curtime

              + "&" + FRPrivilegeFilterHelper.FR_DIGITALSIGNATURE_INFO + "=" + signInfo;   // 模拟拼接url,其实就是原有正常请求之后添加上签名的当前时间,和签名信息

%>

<html>

<head>

   <title>Privilege Demo</title>

</head>

<body bgcolor="#FFFFFF" style="padding: 0pt; border: 0pt none; margin: 0pt; overflow: hidden;">

    <iframe id="frame" src="<%=path%>" name="frame

</body>

</html>

报表工程得到报表请求后进行验证,对reportlet参数值、op参数值、报表系统中当前用户名、发送来的系统时间进行数字签名验证是否正确。

且若用户系统发送来的签名时系统时间,与当前时间差超过90秒,将视为超时。如果都验证通过,则可以访问报表,否则提示没有权限查看。

10、重启服务器

重启用户系统服务器及报表服务器(注意:必须先启动用户系统再启动报表系统),设置即可生效,效果如上图。

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢