当打开或编辑互动白板时,白板服务会通过回调的形式获取您的权限及个人信息。通过阅读本文,您可以了解回调服务的实现逻辑以及回调接口的详情。

回调服务实现

回调接口详情请参见回调接口详情。以Java语言为例,回调服务接口的主要实现逻辑如下所示:

public ResponseResult<Object> callback(HttpServletRequest request){
        // 假设控制台设置的回调地址为(如部署在ecs **.**.**.**,端口为****,建议使用HTTPS和域名)
        String appCallbackUrl = "http://**.**.**.**:****/callback";
        
        // 假设控制台设置的回调鉴权码为callbackSecret
        String appCallbackAuth = "callbackSecret";

        // 获取eventType和requestId
        String eventType = request.getParameterMap().get("eventType")[0];
        String requestId = request.getParameterMap().get("requestId")[0];
    
        // 从request提取params和headers
        // ...
    
        // 验证签名(可选,根据控制台设置的回调鉴权码进行鉴权,保证回调安全性,具体实现请参照回调示例代码)
        boolean verify = SignUtil.verifySign(appCallbackAuth, "POST", appCallbackUrl, params, headers);
        // 回调鉴权失败
        if(!verify){
            return ResponseResult.getErrorResult(requestId, "1000", "CallBackVerifyFailure");
        }

        switch (eventType) {
            // 用户权限回调处理
            case "userPermissionCallback":
                //回调逻辑,出入参数详见下文:回调接口详情
            // 白板元信息回调处理
            case "whiteBoardProfileCallback": 
                //回调逻辑,出入参数详见下文:回调接口详情
            // 用户元信息回调处理
            case "userProfileCallback":
                //回调逻辑,出入参数详见下文:回调接口详情
            // 合法域名校验失败回调通知
            case "hostCheckCallback":
                //回调逻辑,出入参数详见下文:回调接口详情
        }
    }

完整代码请参见whiteboard-callbackservice-demo

回调服务验签

互动白板服务会根据配置的回调鉴权码在HTTP(含HTTPS)回调时增加特定签名头,供回调消息接收服务端进行签名认证,以防止非法或无效请求。

签名机制:互动白板服务在发起回调请求时,会根据应用配置的回调鉴权码+公共参数+自定义参数进行签名,签名结果串与参与签名的公共参数一起包含在Headers中发起请求,回调消息接收方可依此进行验签。签名公共参数如下所示:

参数 类型 是否必选 描述
A-App-Id String 签名App标识,取值:WB。
A-Signature String 签名结果串。
A-Signature-Method String 签名方式,取值:HMAC-SHA1。更多信息,请参见HMAC-SHA1签名逻辑
A-Timestamp String 请求的时间戳。日期格式按照ISO8601标准表示,使用UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ。例如:2019-12-29T12:00:00Z为北京时间2019年12月29日的20点0分0秒。
A-Signature-Version String 签名算法版本,取值:1.0。
A-Signature-Nonce String 唯一随机数。在不同请求间使用不同的随机数值,防止网络重放攻击。

以Java语言为例,HMAC-SHA1验签逻辑如下所示:

private static final String ALGORITHM_NAME = "HmacSHA1";
private static final String ENCODING = "UTF-8";

/**
 * @param signSecret 回调鉴权码
 * @param method     请求方式,取值POST
 * @param path       回调服务URL
 * @param params     请求参数,KV形式
 * @param headers    请求头部(含签名结果串和签名公共参数),header名全小写
 */
public static boolean verifySign(String signSecret, String method, String path,
                                 Map<String, String> params,
                                 Map<String, String> headers){
    
    // 1. 获取签名结果串
    String signature = headers.remove(SIGNATURE);
        
    // 2. 请求params、headers、结果串等入参数检查,非空检查及签名方式、算法版本检查
    // ...
    
    // 3.构造签名字符串stringToSign
    //   3.1 从headers中提取签名公共参数signedHeaders
    //   3.2 构造规范化的params/signedHeaders字符串(参数按key排序后,组合成&key=value形式)
    //   3.3 与method, path一起构造签名字符串stringToSign
    
    // 4. 计算签名
    String expectedSignature = sign(stringToSign, signSecret + "&");
   
    // 5. 校验签名
    return signature.equals(expectedSignature);   
}
    

/**
 * HMAC-SHA1签名计算
 */
public static String sign(String stringToSign, String signSecret) {
    try {
        Mac mac = Mac.getInstance(ALGORITHM_NAME);
        mac.init(new SecretKeySpec(
                signSecret.getBytes(ENCODING),
                ALGORITHM_NAME
        ));
        byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));
        String signBase64 = DatatypeConverter.printBase64Binary(signData);
        return percentEncode(signBase64);
    } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
        throw new IllegalArgumentException(e.toString(), e);
    }
}

完整代码请参见whiteboard-callbackservice-demo

回调接口详情

互动白板提供的回调接口如下所示:

  • 用户鉴权回调:回调客户服务端查询某用户(userId)访问某文档(docKey)的权限。

    回调入参

    参数 类型 说明
    eventType String 回调类型:userPermissionCallback。
    requestId String 自动生成的请求ID,建议传回。
    userId String 被查询权限的用户ID,由纯数字组成。
    docKey String 被查询权限的docKey。
    permissionType String 权限类型。取值:
    • read:只读。
    • edit:读写。

    返回示例

    {
        "requestId": "0E85E1C9-4A68-49E5-965A-22F628B209C6", // 自动生成的请求ID,建议回传白板服务端,以便日志跟踪
        "responseSuccess": true,
        "result": {
            true
        },
        "errorCode": null,
        "errorMsg": null
    }
  • 查询用户信息回调:回调客户服务端批量查询的用户信息。

    回调入参

    参数 类型 说明
    eventType String 回调类型:userProfileCallback。
    requestId String 自动生成的请求ID,建议传回。
    userIds String 被查询信息的用户ID,多个使用英文逗号(,)分隔,最多30个,每个ID由纯数字组成。

    返回示例

    {
        "requestId": "CE47143D-9700-4756-856A-BB22FEBE4DAE", // 自动生成的请求ID,建议回传白板服务端,以便日志跟踪
        "responseSuccess": true,
        "result": {
           "userProfileList": [
                {
                    "userId": "123",
                    "avatarUrl": "http://www.avatarset/****.jpg",
                    "nick": "Janice",
                    "nickPinyin": "Pinyin_Janice"
                },
                {
                    "userId": "456",
                    "avatarUrl": "http://www.avatarset/****.jpg",
                    "nick": "Mildred",
                    "nickPinyin": "Pinyin_Mildred"
                },
                {
                    "userId": "789",
                    "avatarUrl": "http://www.avatarset/****.jpg",
                    "nick": "Tina",
                    "nickPinyin": "Pinyin_Tina"
                }
            ]
        },
        "errorCode": null,
        "errorMsg": null
    }
  • 查询白板文档信息回调:回调客户服务端查询白板文档的信息。

    回调入参

    参数 类型 说明
    eventType String 回调类型:whiteBoardProfileCallback。
    requestId String 自动生成的请求ID,建议传回。
    docKey String 白板文档唯一标识符。

    返回示例

    {
        "requestId": "B29ADDF9-D089-460A-AF7D-BDE5DA112E4E", // 自动生成的请求ID,建议回传白板服务端,以便日志跟踪
        "responseSuccess": true,
        "result": {
            "name": "white_board" // 白板名称
        },
        "errorCode": null,
        "errorMsg": null
    }
  • 合法域名校验失败回调:回调客户服务端通知客户端访问域名异常。

    回调入参

    参数 类型 说明
    eventType String 回调类型:hostCheckCallback。
    requestId String 自动生成的请求ID,建议传回。
    docKey String 白板文档唯一标识符。
    originHost String 客户端访问白板时的域名。
    hostErrorMsg String 域名校验失败的信息。

    返回示例

    {
        "requestId": "FE22D613-D3C6-4A58-87CA-F21FC85AA08E", // 自动生成的请求ID,建议回传白板服务端,以便日志跟踪
        "responseSuccess": true,
        "result": true, // 表示接收回调通知成功
        "errorCode": null,
        "errorMsg": null
    }