为了升高第三方利用集成华为云会议难度,并且晋升凋谢接口的安全性,华为云会议凋谢能力中反对基于App ID的鉴权形式。App ID是一个利用的标识,同一个App ID能够同时在第三方的桌面终端、挪动终端、Web利用上应用。

App ID鉴权原理

图1 第三方客户端App ID鉴权流程

鉴权前提:

  1. 开发者在华为云会议管制台上为本人的利用申请AppID,并获取App ID和App Key。
  2. 开发者在本人的服务端集成Signature生成算法,请参考“第三方服务集成Signature生成算法”。
  3. SDK初始化时传入App ID,请参考《客户端SDK参考》中的“初始化”局部。

鉴权过程:

  1. 第三方客户端将User ID(第三方User ID)发送给第三方服务器。
  2. 第三方服务器依据App ID、User ID、App Key等,生成鉴权用的签名资料Signature。
  3. 第三方服务端返回Signature,以及ExpireTime和Nonce值。
  4. 第三方客户端调用客户端SDK的Login接口,参数为User ID、Signature、ExpireTime和Nonce。
  5. 客户端SDK去华为云会议服务端鉴权。
  6. 鉴权通过后SDK获取接入Token。该Token对第三方客户端不可见,由SDK负责保护和刷新。

图2 第三方服务端App ID鉴权流程

鉴权前提:

  1. 开发者在华为云会议管制台上为本人的利用申请AppID,并获取App ID和App Key。
  2. 开发者在本人的服务端集成Signature生成算法,请参考“第三方服务集成Signature生成算法”。

鉴权过程:

  1. 第三方服务端依据调用的业务接口所需的User ID(第三方User ID),加上App ID、App Key、ExpireTime和Nonce,生成鉴权用的签名资料Signature。
  2. 第三方服务端调用华为云会议服务端的AppID鉴权接口(REST接口)。
  3. 华为云会议服务端鉴权通过后,返回接入Token。
  4. 第三方服务端应用接入Token调用其余业务接口。

阐明:

1. 接口Token有效期是12~24小时。

2. 生成Signature和调用appAuth接口时能够不带User ID,如果不带User ID默认是创立企业时的创建者(企业Owner)。

3. User ID须要第三方利用保障在同一个企业内是惟一的。如果第三方开发者是SP,同一个利用在多个企业应用,接口中除了带User ID外,还须要带Corp ID(企业ID)

4. 如果须要应用华为云会议通讯录的状况下,在登录鉴权过程中还能够携带邮箱、姓名、电话号码等信息,这些信息将被写入华为云会议的通讯录中。

App ID的申请

  1. 应用华为云账号,登录华为云会议控制台。前提是该华为云账号曾经购买了华为云会议服务或者曾经绑定了华为云会议企业管理员帐号,请参考“开发流程”章节中的“开发前筹备”。
  2. 点击“利用治理”,再点击“申请利用”。在弹出的创立利用的输入框中输出第三方利用的名称及形容。

    图3 创立利用

阐明:*   请填写实在的联系人姓名和手机号码。*   申请提交后,华为云会议工作人员会在1~3个工作日内实现审核和审批。
  1. 生成App Key

    审批通过后,点击“生成AppKey”再点击“确定”生成App Key。

    图4 生成App Key

阐明:

  1. App Key是生成鉴权签名资料Signature的密钥,须要在第三方服务端妥善保留,不要泄露进来,否则会呈现被盗用会议资源的危险。
  2. App Key只能保留在第三方服务端,不能保留在第三方终端中,否则很容易被反编译获取。
  3. App Key须要妥善保留,遗失后只能重置,不能找回。从新生成App Key原来的App Key将会在一个月后生效。

第三方服务集成Signature生成算法

App只在单个企业内应用的状况下,生成鉴权签名资料Signature的算法如下:
Signature = HexEncode(HMAC-SHA256((App ID + ":" + User ID + ":" + ExpireTime + ":" + Nonce), appKey))

App是SP开发的,须要在多个企业内应用的状况下,生成鉴权签名资料Signature的算法如下:

  • 作为企业普通用户,对本人的会议治理:
    Signature = HexEncode(HMAC-SHA256((App ID + ":" + CorpID + ":" + User ID + ":" + ExpireTime + ":" + Nonce), appKey))
  • 作为企业管理员,对企业资源进行治理:
    Signature = HexEncode(HMAC-SHA256((App ID + ":" + CorpID + "::" + ExpireTime + ":" + Nonce), appKey))
    阐明:

    作为企业管理员是也能够带User ID,这个User ID必选具备管理员权限。

  • 作为SP管理员,对SP资源进行治理(如创立企业或者调配企业资源等):
    Signature = HexEncode(HMAC-SHA256((App ID + ":::" + ExpireTime + ":" + Nonce), appKey))

算法阐明:

  1. HMAC-SHA256的输出数据是App ID、CorpID(可选)、User ID(可选)、ExpireTime、Nonce值,两头用“:”分隔。如d5e1785afbe44c2588b642446652489e:alice@ent01:1604020600:EycLQsHwxhzK9OW8UEKWNfH2I3CGR2nINuU1EBpQ

    阐明:
    SP模式下即便User ID或者Corp ID和User ID不填的状况下,对应的“:”不能省略。

  2. HMAC-SHA256的密钥是App Key。如tZAeEXWggfxMq32T
  3. HMAC-SHA256生成的二进制数须要转换为十六进制字符串(HexEncode),上述的数据和密钥最终生成的Signature如下:2a8c780cee3dbfe210384c3f95380732d55dfc81cfa49c5a6c44f3c1b3c2455d
  4. ExpireTime:鉴权签名资料Signature的过期工夫戳。单位是秒。比方以后的零碎的工夫戳是1604020000,Signature有效期设置成10分钟,则ExpireTime = 1604020000+10*60 = 1604020600
  5. Nonce:随机字符串,每次计算鉴权签名资料Signature时都必须不同。字符串长度为32~64字节

阐明:

1. 因为鉴权签名资料Signaure是有有效期的,所以第三方服务端的零碎工夫和华为云会议服务端的零碎时间误差不能太大(小于ExpireTime中的有效期,如上例中的10分钟)。华为云会议服务端工夫曾经跟规范NTP工夫同步。

2. ExpireTime为0,示意永远不过期。为了避免重放攻打,不倡议将ExpireTime设置为0。

Java版本的Signature生成算法源代码

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class HmacSHA256 {

 //十六进制字符集 private final static char[] DIGEST_ARRAYS = {     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };   /**  * 性能:Signature生成算法  * 输出参数:  *          1.data: HMAC-SHA256的输出数据  *          2.key: App Key  * 输入参数:十六进制字符串编码的HMAC-SHA256值  */ public static String encode(String data, String key) {     byte[] hashByte;     try {         Mac sha256HMAC = Mac.getInstance("HmacSHA256");         SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");         sha256HMAC.init(secretKey);         hashByte = sha256HMAC.doFinal(data.getBytes("UTF-8"));     } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {         return null;     }     return bytesToHex(hashByte); } /**  * 性能:byte类型数组转换成十六进制字符串  * 输出参数:  *          1.bytes:被转换的字节数组  * 输入参数:十六进制字符串  */ private static String bytesToHex(byte[] bytes) {     StringBuffer hexStr = new StringBuffer();     for (int i = 0; i < bytes.length; i++) {         hexStr.append(DIGEST_ARRAYS[bytes[i] >>> 4 & 0X0F]);         hexStr.append(DIGEST_ARRAYS[bytes[i] & 0X0F]);     }     return hexStr.toString(); }

}

Python版本的Signature生成算法源代码
import hmac
from hashlib import sha256

class HmacSHA256:

  def __init__(self, sig_data, sig_key):     self.data = sig_data     self.key = sig_key  def encode(self):     try:         sig_data = self.data.encode('utf-8')         secret_key = self.key.encode('utf-8')         signature = hmac.new(secret_key, sig_data, digestmod=sha256).hexdigest()     except Exception as e:         print (e)         raise e      return signature

C++版本的Signature生成算法源代码

<pre class="ctnc" style="box-sizing: border-box; overflow: auto; font-family: Consolas, &quot;Bitstream Vera Sans Mono&quot;, &quot;Courier New&quot;, Courier, monospace; font-size: 1em; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(250, 250, 250) !important; color: rgb(29, 33, 41) !important; border: 1px solid rgb(231, 233, 250); line-height: 22px; padding: 0px 1em; transition: background-color 1s ease 0s;">#include <openssl/hmac.h>

include <string.h>

include <iostream>

using namespace std;

const int HMAC_ENCODE_SUCCESS = 0;
const int HMAC_ENCODE_FAIL = -1;
const int HMAC_SHA256_STR_LEN = 65;

/**

  • 性能: 字节流转换成十六进制字符串
  • 输出参数:
  • 1.input: 字节流指针
  • 2.len: 字节流字节数
  • 输入参数:
  • 3.output: 输入缓冲区
  • 6.output_length: Signature字符串长度
  • 返回值:
  • 0:失败
  • 大于0的整数:转换后的字符串长度
    */
    int Byte2HexStr(char output, unsigned char input, unsigned int len)
    {
    if ((NULL == output) || (NULL == input))
    {

      return 0;

    }

    unsigned int i = 0;
    for (i = 0; i < len; i++)
    {

      sprintf_s(output + 2*i, HMAC_SHA256_STR_LEN-2*i, "%x%x", (input[i] >> 4) & 0x0F, input[i]&0x0F);

    }

    (output + 2i) = '\0';

    return 2*i;
    }

/**

  • 性能: Signature生成算法
  • 输出参数:
  • 1.key: App Key
  • 2.key_length: App Key的字符串长度
  • 3.input: HMAC-SHA256的输出数据
  • 4.input_length: HMAC-SHA256的输出数据的字符串长度
  • 输入参数:
  • 5.output: Signature输入缓冲区
  • 6.output_length: Signature字符串长度
  • 返回值:
  • 0:胜利
  • -1:失败
    */
    int HmacEncode(const char * key, unsigned int key_length,
    const char * input, unsigned int input_length,
    char output[HMAC_SHA256_STR_LEN], unsigned int &output_length) {

    //计算HMAC_SHA256的字节流
    const EVP_MD * engine = EVP_sha256();

    unsigned char byte_output = (unsigned char)malloc(EVP_MAX_MD_SIZE);
    if (NULL == byte_output)
    {

      output_length = 0;  return HMAC_ENCODE_FAIL;

    }
    unsigned int byte_output_length = 0;

    HMAC_CTX *ctx;
    ctx = HMAC_CTX_new();

    HMAC_Init(ctx, key, strlen(key), engine);
    HMAC_Update(ctx, (unsigned char*)input, strlen(input));
    HMAC_Final(ctx, byte_output, &byte_output_length);

    HMAC_CTX_free(ctx);

    //HMAC_SHA256的字节流转换成十六进制字符串
    int ret = Byte2HexStr(output, byte_output, byte_output_length);
    free(byte_output);

    if (0 == ret)
    {

      output_length = 0;  return HMAC_ENCODE_FAIL;

    }
    else
    {

      output_length = ret;  return HMAC_ENCODE_SUCCESS;

    }

阐明:

C++的Signature生成算法基于openssl 1.1.0以上版本实现。openssl库须要开发者本人编译和装置,请参考openssl官网。

JavaScript版本的Signature生成算法源代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"> </script>
<script>

 /**  *  1、重要揭示:生成Signature的算法不要放在前端代码中,否则会导致App Key泄露,从而导致企业资源被盗  *  2、本示例代码仅供调试时应用  */ function genSignature(data,appKey){     var sign = CryptoJS.HmacSHA256(data,appKey).toString();     return sign }

</script>

集成UI SDK的第三方客户端App ID鉴权

第三方客户端初始化SDK时,须要传入当时申请好的App ID。

  • Android SDK的初始化接口,请参考《客户端SDK参考》中“Android SDK”的“初始化”章节。
  • iOS SDK的初始化接口,请参考《客户端SDK参考》中“iOS SDK”的“初始化”章节。
  • Windows SDK的初始化接口,请参考《客户端SDK参考》中“Windows SDK”的“初始化”章节。
  • Mac SDK的初始化接口,请参考《客户端SDK参考》中“Mac SDK”的“初始化”章节。

第三方客户端登录时,从第三方服务端获取Signature、ExpireTime和Nonce后,调用终端SDK的Login接口实现鉴权。

  • Android SDK的Login接口,请参考《客户端SDK参考》中“Android SDK”的“登录”章节。
  • iOS SDK的Login接口,请参考《客户端SDK参考》中“iOS SDK”的“登录”章节。
  • Windows SDK的Login接口,请参考《客户端SDK参考》中“Windows SDK”的“登录”章节。
  • Mac SDK的Login接口,请参考《客户端SDK参考》中“Mac SDK”的“登录”章节。

第三方服务端App ID鉴权

第三方服务端通过AppID鉴权接口,实现App ID鉴权,并获取接入Token。请参考《服务端API参考》中的“执行App ID鉴权”章节。

本文由华为云公布