历史版本3 :CAS单点登录插件 返回文档
编辑时间: 内容长度:图片数:目录数: 修改原因:

目录:

1. 概述编辑

1.1 问题描述

当用户想要将 FineReport 报表工程集成自己的系统时,可以在登录自己系统的同时登录报表平台。例如用户集成了 OA 系统和平台系统,想要在登录 OA 的同时就登录平台,此时需要使用到单点登录。单点登录的方法除了前端 Ajax 单点( Ajax 跨域异步单点登录 )以外,还可以使用后台登录的方式。做好后台登录后,在 OA 等其他系统访问报表平台或报表地址,将无需重复登录。

1.2 实现思路

通过在 web.xml 中增加拦截请求,Java 调用 FineReport 后台登录接口,来实现后台登录。

2. 操作方法编辑

2.1 web.xml

在 web.xml 中增加 FineReport 相关地址的拦截代码:


<?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>Auther</filter-name>   
    <filter-class>com.fr.io.AuthFilter</filter-class>   
</filter>   
<filter-mapping>   
    <filter-name>Auther</filter-name>   
    <url-pattern>/decision/view/report</url-pattern>  //拦截report 
</filter-mapping> 
<filter-mapping>   
    <filter-name>Auther</filter-name>   
    <url-pattern>/decision/view/form</url-pattern>    //拦截form
</filter-mapping>
<filter-mapping>   
    <filter-name>Auther</filter-name>   
    <url-pattern>/decision</url-pattern>    //拦截pc平台
</filter-mapping>
<filter-mapping>   
    <filter-name>Auther</filter-name>   
    <url-pattern>/decision/url/mobile</url-pattern>  //拦截移动端平台
</filter-mapping> 
</web-app>

2.2 Java 代码

在 Java 中调用后台登录接口,有两种方式:cookie 和 session,根据实际情况选其一即可。

2.2.1 cookie


package com.fr.io;
import com.fr.decision.authority.data.User;
import com.fr.decision.webservice.exception.user.UserNotExistException;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.login.TokenResource;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.log.FineLoggerFactory;
import com.fr.web.utils.WebUtils;
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 java.io.IOException;
public class AuthFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)arg0;
HttpServletResponse res=(HttpServletResponse)arg1;
String user= "sysadmin";//获取用户名,此处需要根据实际如何获取登录用户名修改
FineLoggerFactory.getLogger().info("user="+user);
String token_old = TokenResource.COOKIE.getToken(req);
FineLoggerFactory.getLogger().info("token_old="+token_old);
//获取登录状态,没登录进入判断是否单点
if (token_old == null) {
if(user==null||"".equals(user.trim())) {
arg2.doFilter(req, res);
return;
}
try {
User U = UserService.getInstance().getUserByUserName(user);
if (U == null) {
throw new UserNotExistException();
}
FineLoggerFactory.getLogger().info("cookie不存在,开始登录当前用户");
String token = LoginService.getInstance().login(req, res, user);
req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token);
arg2.doFilter(req, res);
}   catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
} else {
FineLoggerFactory.getLogger().info("cookie已存在,用之前用户登录");
arg2.doFilter(req, res);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}

注:如果遇到 IP 访问单点正常,域名访问立即提示登录信息失效,可能是因为 cookie 跨域了。映射的时候,域名跟 IP 不在同一个域,因为 cookie 是存在域下面的。这种场景,可以用 session 存放 Token。

2.2.2 session


package com.fr.io;
import com.fr.decision.authority.data.User;
import com.fr.decision.webservice.exception.user.UserNotExistException;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.log.FineLoggerFactory;
import com.fr.web.utils.WebUtils;
import java.io.IOException;
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;
public class AuthFilter implements Filter {
   public void destroy() {
   }
   public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws 
IOException, ServletException {
      HttpServletRequest req = (HttpServletRequest)arg0;
      HttpServletResponse res = (HttpServletResponse)arg1;
      String user = "sysadmin";//获取用户名,此处需要根据实际如何获取登录用户名修改
      System.out.println("user=" + user);
      String token_old = (String)req.getSession().getAttribute("fine_auth_token");
      System.out.println("sso test token_old:" + token_old);
      if(token_old == null) {
         if(user == null || "".equals(user.trim())) {
            arg2.doFilter(req, res);
            return;
         }
         try {
            User e = UserService.getInstance().getUserByUserName(user);
            if(e == null) {
               throw new UserNotExistException();
            }
            FineLoggerFactory.getLogger().info("cookie不存在,开始登录当前用户");
            String token = LoginService.getInstance().login(req, res, user);
            System.out.println("sso test token_new:" + token);
            req.getSession().setAttribute("fine_auth_token", token);
            System.out.println("登陆成功");
            FineLoggerFactory.getLogger().info("登录成功");
            arg2.doFilter(req, res);
         } catch (Exception var11) {
            FineLoggerFactory.getLogger().error(var11.getMessage(), var11);
            System.out.println("我报错了1号");
         }
      } else {
         System.out.println("cookie已存在,用之前用户登录");
         FineLoggerFactory.getLogger().info("cookie已存在,用之前用户登录");
         arg2.doFilter(req, res);
      }
   }
   public void init(FilterConfig arg0) throws ServletException {
   }
}

2.3 编译 class 文件

编译 Java 代码生成 class 文件,将文件放在%FR_HOME%\webapps\webroot\WEB-INF\classes\com\fr\io路径下,重启报表工程。

注:class 文件放置路径与 Java 包名有关,根据实际修改即可。

1581914318549043.png

2.4 访问格式

1)PC 端

  • 平台:http://192.168.1.65:8081/webroot/decision

  • 模板:http://192.168.1.65:8081/webroot/decision/view/report?viewlet=GettingStarted.cpt

2)移动端

  • 平台:http://192.168.1.65:8081/webroot/decision/url/mobile

  •  模板:http://192.168.1.65:8081/webroot/decision/view/report?viewlet=GettingStarted.cpt&op=h5

注1:目前的最新逻辑,移动端跟 PC 端的 token 保持一致了,后台登录代码通用,PC 端跟移动端访问的 URL 有区别。

注2:旧版本由于移动端 token 跟 PC 端的逻辑不一致,移动端访问链接需加上 &__device__=iPhone&terminal=H5&deviceType=iPhone 这个参数,才能获取移动端 token,新版兼容旧版。