---
order: 99
---
# 与SuccezBI3.x单点登录

本文讲述 SuccBI4.x及后续版本(下文用本系统指代) 如何与SuccezBI3.x（下文用3.x指代）共享用户库以及单点登录：

\[\[toc]]

## 使用3.x的用户库{#use-3\_x-users}

由于本系统和3.x所使用的用户表结构存在差异，需要将3.x的用户数据同步到本系统内置用户表中（可以通过数据加工进行提取）

需要注意的是 3.x 直接使用 MD5 对密码进行加密，本系统在给密码加盐后再对密码使用 sha1 进行加密，由于MD5 是非对称加密，无法解析出用户的明文密码,同步数据时应该忽略掉密码，

由于可能3.x环境中新增了用户，没有及时同步到本系统中的问题，用户在本系统中登录过程为：
根据登录用户账号与密码向3.x用户库中查找用户信息，并校验密码登录密码是否正确，校验成功后，检查本系统内置用户库中是否存在该用户，不存在则向本系统用户库中添加一个用户

考虑到登录流程与使用本系统内置登录流程不一样，需要使用[登录脚本](/dev/hooks/security-action)功能做到这一点：

脚本模板如下：

```javascript
"use strict";

var db = require("svr-api/db");
var utils = require("svr-api/utils");
/**
 * 当一个用户使用用户名密码方式登录时校验账号密码时候调用。
 *
 * 注意：
 * 	1. 当执行此回调函数时，用户还未登录成功，系统会根据此函数返回的结果决定后续的操作
 * 	2. 账号为 admin 的用户登录时不受这个脚本函数的影响
 * 
 * @param request
 * @param response 这个属性不再使用
 * @param userId 用户输入的用户ID或者手机号
 * @param password 明文密码
 * @param userDirectory 用户目录。用于标识用户的来源，系统内置的区分有：`sys`表示系统用户，`external`表示外部用户
 * @returns
 * 	1. 如果明确返回`UserInfo`对象，那么将绕过系统默认的登录验证逻辑，直接使用返回的用户信息登录。  
 * 	2. 如果抛出异常，那么将导致用户登录失败，异常信息会显示给用户，可用于进行额外的登录验证判断。  
 * 	3. 如果没有返回值，那么将进行系统默认的登录校验 
 */
function verifyLoginPassword(request, userId, password, userDirectory) {
    var ds = db.getDataSource("${datasourceName}"); //获取与3.x用户库的连接， datasourceName 为本系统数据源中对3.x用户库的数据源名称,使用的时候请替换为正确内容
    var sqlResult = ds.executeQuery("select * from szsys_1_metauser where USERID = ?", [userId]); // 如果用户表被替换，请将表名替换为正确的内容
    if(!sqlResult.length){
        throw new Error("用户不存在或不可用");
    }
    var user = sqlResult[0];
    if (!user || !user.ENABLED) {
        throw new Error("用户不存在或不可用");
    }

    if (user.PASSWORD !== utils.md5(password +'\t'+  user.SALT + "\t")) {
        throw new Error("密码不正确");
    }
    var defaultDs = db.getDefaultDataSource(); // 本系统默认数据连接，存储了内置的用户表
    var userTableData = defaultDs.openTableData("SZSYS_4_USERS");
    sqlResult=  userTableData.executeQuery("select * from SZSYS_5_USERS WHERE USER_ID = ?", [userId]);
    var ret;
    if (!sqlResult.length) {
        userTableData.insert({ USER_ID: userId, USER_NAME: user.USERNAME, ENABLED: 1, EMAIL: user.EMAIL, PHONE: user.MB, SALT: utils.randomString(), PASSWORD: utils.uuid() });
        ret = {
            userId: userId,
            userName: user.USERNAME,
            email: user.EMAIL,
            enabled: true,
            phone: user.MB
        };
    } else {
        var user4 =  sqlResult[0];
        ret = {
            userId: userId,
            userName: user4.USER_NAME,
            email: user4.EMAIL,
            enabled: true,
            phone: user4.PHNOE
        };
    }
    return ret;
}
```

注意：

1. 这个登录脚本的使用前提是在本系统中配置了包含 3.x 用户库的数据源
2. 需要替换其中 `var ds = db.getDataSource("${datasourceName}")` 中的datasourceName 为本系统中所配置 3.x 用户库数据源名称
3. 若3\_x 用户表也被替换，`var sqlResult = ds.executeQuery("select * from szsys_1_dimuser where USERID = ?", [userId]);` 这一行中所执行的sql 所查询的表也需要改变

## 将3.x系统页面嵌入到本系统中{#embed-3\_x}

这里与[将本系统嵌入第三方系统](../../dev/integrate/link-3rd-page.md)采用一样的方案，只是相对于第三方应用，3.x系统已经内置了：

- 验证认证信息然后自动登录的接口。
- 配置本系统的系统证书为信任证书界面。

通过本系统访问3.x系统流程如下：

![流程图](./images/embed-page-with3_x.png)

在完成如下配置后，即可在已经登录本系统的情况下从本系统跳转免登录访问到3.x系统：

1. 在本系统中生成[系统证书](../../sys-settings/security/trustedapps.md#systemcert)。

2. 在 3.x 环境中配置本系统的系统证书，信任证书配置地址为 **系统设置** > **安全** > **证书管理** > **信任证书**：

   ![3.x 信任证书](./images/3_xtrusts.png)

3. 如果本系统与3.x系统不是部署在同一个域名中并且需要使用iframe来展示3.x系统页面，则还需要针对3.x系统处理[跨域问题](../../dev/integrate/link-3rd-page.md#cors)。

PS：本系统配置与3.x 信任证书的配置参数名对应为：

| 本系统参数 | 3.x证书参数 |
| ---------- | ----------- |
| 系统ID     | 名称        |
| 系统名称   | 标题        |
| 证书       | 证书        |

将本系统嵌入第三方系统页面示例参照：[示例地址](../../dev/integrate/link-3rd-page.md)。

## 将本系统链接嵌入到3.x系统中{#embed-into-3\_x}

这里与[本系统中嵌入第三方应用链接](../../dev/integrate/embed-into-3rd.md)采用一样的方案，相对于第三方应用，3.x系统已经内置了：

- [系统证书的生成](https://wiki.succez.com/pages/viewpage.action?pageId=144769315)。
- 使用证书私钥加密生成认证信息的接口。

通过3.x系统访问本系统流程如下：
![流程图](./images/embeded-page-in3_x.png)

在完成如下配置后，即可在已经登录3.x系统的情况下从3.x系统跳转免登录访问到本系统：

1. 在3.x系统生成证书，查看地址为 **系统管理** > **安全** > **证书管理** > **系统证书**

   ![3.x 系统证书](./images/3_xcert.png)

2. 将3.x系统的系统证书配置作为注册为[本系统证书授信应用](../../sys-settings/security/trustedapps.md#trust-cert)

3. 如果本系统与3.x系统不是部署在同一个域名中并且需要使用iframe来展示本系统的页面，则还需要针对本系统处理[跨域问题](../../dev/integrate/embed-into-3rd.md#cors)。

注意：

- 本系统证书授信应用配置与3.x 系统证书的配置参数名对应为：

  | 本系统参数 | 3.x证书参数 |
  | ---------- | ----------- |
  | 应用ID     | 名称        |
  | 应用名称   | 标题        |
  | 证书       | 证书        |

- 请将3.x系统证书中生成的`证书`选项复制到本系统的证书授信应用对应的`证书`中：因为3.x系统没有提供自定义系统证书私钥的方式。

下面以[3.x系统报表中插入iframe](https://wiki.succez.com/pages/viewpage.action?pageId=149913674)访问本系统为例：

![iframe](./images/3_x-example-iframe.png)

![iframe](./images/3_x-exmaple-iframe-result.png)
