电子表格FineReport7.1.1
大小:148.2M 适用平台:windows/linux
问题描述如下图集成报表后,希望不同的用户登录,所能看到的报表是不同的,没有权限的用户查看报表时提示没有权限:
解决方案通过数字签名的方式来验证发送的报表请求,需要带有与FR约定的数字签名方式签名之后的信息,FR验证签名信息合法才允许访问报表,否则返回没有权限。注:本方案使用 MD5+RSA数字签名方式。
适用情况前面3个章节的权限控制方式是针对那些比较简单的系统而言的,那么对那些很复杂的系统,使用前面3中权限配置方式就行不通了,这个时候就可以用数字签名的方式进行权限配置。
前提准备报表工程:如直接使用内置Jetty服务器中的报表工程WebReport,端口为8075;用户系统:如用户工程(在PFDemo目录)发布于Tomcat服务器,端口为8080;PFDemo下有文件login.html(用户的登陆界面)、index.jsp(登陆后的主界面)、report.jsp(对报表请求进行签名,将签名信息加入请求中转发给报表工程)。注:下面有对应文件的完整代码。配置好报表端的身份验证>并与用户系统实现单点登录:如该例我们使用数据集验证,用户-密码服务器数据集定义如下:
点击管理系统>用户管理>设置,认证方式使用默认的平台内置认证,配置用户同步数据集,如下图:
拷贝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下。
用户系统中添加一个web接口给报表工程提供公钥这个接口是一个地址,比如在用户系统中注册一个servlet,访问这个servlet来获得公钥,http://localhost:8080/PFDemo/DemoServer?cmd=getkey:在用户系统的PFDemo\WEB-INF\web.xml中添加一个servlet:
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(); }}
报表工程中获取用户系统的公钥选择权限配置>详细权限配置;点击提交:
用户系统发送报表请求加入数字签名信息如最上图中登陆后的主界面为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', '');}%>
Privilege Demo Current user: <%=username%> | |
<% if ('A'.equals(request.getSession().getAttribute('username'))) { %>
|
当点击左边报表节点时,触发viewReport这个js方法,通过iframe执行report.jsp文件,并传递请求查看的报表名字。在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,其实就是原有正常请求之后添加上签名的当前时间,和签名信息%>
报表工程得到报表请求后进行验证,对reportlet参数值、op参数值、报表系统中当前用户名、发送来的系统时间进行数字签名验证是否正确。且若用户系统发送来的签名时系统时间,与当前时间差超过90秒,将视为超时。如果都验证通过,则可以访问报表,否则提示没有权限查看。
重启服务器重启用户系统服务器及报表服务器(注意:必须先启动用户系统再启动报表系统),设置即可生效,效果如上图。相关demo详细请前往权限集成java版demo页面下载,选择权限集成-JAVA资源>demo.rar即可。
何谓数字签名?目前的数字签名是建立在公共密钥体制基础上,它是公用密钥加密技术的另一类应用。它的主要方式是:报文的发送方从报文文本中生成一个128位的散列值(或报文摘要)。发送方用自己的私人密钥对这个散列值进行加密来形成发送方的数字签名。这个数字签名将作为报文的附件和报文一起发送给报文的接收方。报文的接收方首先从接收到的原始报文中计算出128位的散列值(或报文摘要),再用发送方的公用密钥来对报文附加的数字签名进行解密。如果两个散列值相同、那么接收方就能确认该数字签名是发送方的。通过数字签名能够实现对原始报文的鉴别。