1、前提准备报表工程:如直接使用内置Jetty服务器中的报表工程WebReport,端口为8075;用户系统:如用户工程(在PFDemo目录)发布于Tomcat服务器,端口为8080;PFDemo下有文件login.html(用户的登陆界面)、index.jsp(登陆后的主界面)、report.jsp(对报表请求进行签名,将签名信息加入请求中转发给报表工程)。注:下面有对应文件的完整代码。配置好报表端的身份验证>并与用户系统实现单点登录:如该例我们使用数据集验证,用户-密码服务器数据集定义如下:
2、登陆平台系统http://localhost:8075/WebReport/ReportServer?op=fr_platform,点击管理系统>用户管理>设置,认证方式使用默认的平台内置认证,配置用户同步数据集,如下图:
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,点击提交:
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" width="100%" height="100%"/> </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" width="100%" height="100%"/></body></html>报表工程得到报表请求后进行验证,对reportlet参数值、op参数值、报表系统中当前用户名、发送来的系统时间进行数字签名验证是否正确。且若用户系统发送来的签名时系统时间,与当前时间差超过90秒,将视为超时。如果都验证通过,则可以访问报表,否则提示没有权限查看。
10、重启服务器重启用户系统服务器及报表服务器(注意:必须先启动用户系统再启动报表系统),设置即可生效,效果如上图。