# 钉钉登录

SuccBI支持与钉钉单点登录,可以直接使用钉钉账号进行身份验证,无需繁琐的登录步骤。

重要说明

  • 需要确保部署SuccBI的服务器可以访问 https://api.dingtalk.com

  • 成为钉钉开发者,拥有开发企业自建应用权限的帐号。

  • 根据钉钉官方文档 (opens new window)完成实现登录第三方网站的配置。

# 钉钉配置

# 创建并配置应用

在开发者后台创建一个H5微应用,并完成通讯录权限和用户个人手机号权限的配置,用于获取用户个人信息。

开发管理页面,根据以下内容配置开发信息。

开发管理

  1. 开发模式: 设置为开发应用
  2. 服务器出口IP: 设置为SuccBI系统的公网域名。详细操作参见文档。 (opens new window)
  3. 应用首页地址: 示例为https://{domain}/{contextPath}/api/auth/doSSOAuthRedirect?ssoid={ssoid}&redirect_uri={redirect_uri}
  4. PC端首页地址: 示例为https://{domain}/{contextPath}/api/auth/doSSOAuthRedirect?ssoid={ssoid}&redirect_uri={redirect_uri}

说明

  • domain 和 contextPath,请替换为环境地址。
  • ssoid 为SuccBI设置的登录方案ID,请根据实际情况替换。
  • redirect_uri,可以设置为/,表示登录成功后跳转到BI设置的首页,也可以按需替换为需要钉钉展示的地址,如/Test/app/test.app 表示跳转到SuccBI 中命名为 Test项目的 test.app中进行展示。redirect_uri需要注意URL转义 (opens new window)

# 添加接口权限

进入权限管理页面,根据以下配置添加接口调用权限。详细操作参见文档。 (opens new window)

添加接口权限

# 设置第三方网站的回调域名

登录与分享

示例: https://{domain}/{contextPath}/api/auth/redirect?ssoid={ssoid}&redirect_url={redirect_url},参数设置见上文描述。

# 版本管理与发布

版本管理与发布

以上配置完毕后,最后需要完成版本的发布。按需设置权限范围。

# 系统设置

需要在系统设置>安全>单点登录中添加一个脚本定制的单点登录方案。

系统设置

# 基本设置

单点登录方案通用设置

基本设置

  1. 启用: 勾选,这里勾选才会启用此单点方式。
  2. 登录方案ID:ID用于唯一标识登录方案,英文字母或数字组成,如dingding,下文中的脚本示例用了此处的dingding,若是改为其他名称,脚本需要做对应的修改。

# 用户匹配规则设置

用户匹配规则设置

  1. 启用: 勾选,这里勾选才会允许作为内部用户登录系统。
  2. 匹配用户依据1: 根据指定的用户信息在用户表中查找对应的用户,找到后将使用指定的用户登录系统。这里设置为移动电话(对应物理字段为PHONE)。
  3. 匹配用户依据2: 如果根据“匹配用户依据1”无法匹配到用户,那么还可以根据第二个用户信息进行匹配。

# 添加单点登录脚本

脚本位置放在系统数据项目,位于 /sysdata/settings/hooks/security.action.ts中,详细设置参考security.action

单点登录脚本

点击展开查看脚本示例代码>>

import utils from "svr-api/utils";
import http from 'svr-api/http';

let appkey = 'dingdnpb1t8cor2fdwqc';// 请按需替换为创建应用的appkey
let appsecret = 'f9UWa7FzRa63FE3GoO6Ku11RB60Uu13FZkyciP6qwHwc7UpsItz5sI_JtwtsG6PS';//请替换为创建应用的秘钥
let dingdingSSOId = "dingding";// 替换为创建的单点登录方案ID

/**
 * 用于构建跳转钉钉授权展示界面的URL,为通过钉钉工作台中打开应用时调用
 */
function onSSOGetAuthRedirectURL(request: HttpServletRequest, response: HttpServletResponse, redirect_uri: string, ssoArgs: SSOArgs): boolean | string {
    let session = request.getSession();
    let state = utils.uuid().substring(0, 5)
    session.setAttribute("state", state);

    let ssoid = request.getParameter('ssoid');
    let url;
    if (ssoid === dingdingSSOId) {
        url = getDingtalkLoginUrl(state, redirect_uri);
    }
    if (url == null) {
        return false;
    }

    // print(url);
    return url;
}

function getDingtalkLoginUrl(state: string, redirect_url: string) {
    // print(appkey);
    return `https://login.dingtalk.com/oauth2/auth?redirect_uri=${encodeURIComponent(redirect_url)}&response_type=code&scope=openid&prompt=consent&client_id=${appkey}&state=${state}`;
}

/**
 * 用于用户在钉钉授权页面点击授权后,跳转到BI时调用(这个地址由 getDingtalkLoginUrl 函数返回URL中的redirect_uri参数决定)
 */
function onSSOCheckTicket(request: HttpServletRequest, response: HttpServletResponse, ssoArgs: SSOArgs): UserInfo | void {
    let ssoid = request.getParameter('ssoid');
    if (ssoid === dingdingSSOId) {
        return doDingTalkAuth(request, response, ssoArgs);
    }
}

function doDingTalkAuth(request: HttpServletRequest, response: HttpServletResponse, ssoArgs: SSOArgs): UserInfo | void {
    let code = request.getParameter('authCode');
    // print("code is " + code);
    if (!code) {
        response.sendRedirect(request.getContextPath() + '/login');
        return;
    }

    let json = JSON.parse(http.request({
        url: "https://api.dingtalk.com/v1.0/oauth2/userAccessToken",
        method: "POST",
        data: {
            clientId: appkey,
            clientSecret: appsecret,
            code,
            grantType: "authorization_code"
        },
        headers: {
            "Content-Type": "application/json"
        }
    }).responseText);
    // print(json);

    let access_token = json.accessToken;

    json = JSON.parse(http.request({
        url: "https://api.dingtalk.com/v1.0/contact/users/me",
        method: "GET",
        headers: {
            "Content-Type": "application/json",
            "x-acs-dingtalk-access-token": access_token
        }
    }).responseText)
    // print(json);


    /* 返回一组用户信息,用于匹配在系统中存储的用户 */
    return <{
        /** id, 同 userId */
        userId: string;
        /** 用户名称, 同 userName */
        USER_NAME?: string;
        /** 部门ID */
        DEPT_ID?: string;
        /** 电话 */
        PHONE?: string;
        /** 邮箱 */
        EMAIL?: string;
        /** 获取头像地址 */
        avatar?: string;
        /** 扩展字段数据, 为用户表字段的名称*/
        [propName: string]: any;
    }>{
            userId: json.unionId,//只传第一个userId都可以,
            USER_NAME: json.nick,
            PHONE: json.mobile,
            EMAIL: json.email,
            avatar: json.avatarUrl === '' ? undefined : json.avatarUrl
        };
}


# 访问SuccBI页面地址

完成以上配置后,可以免密访问SuccBI页面地址。登录后,进入工作台页面,点击Demo应用正常跳转到SuccBI页面。

钉钉工作台页面 授权后登录页面 登录成功页面
是否有帮助?
0条评论
评论