乐趣区

关于程序员:华为云会议开发指南App-ID鉴权介绍

为了升高第三方利用集成华为云会议难度,并且晋升凋谢接口的安全性,华为云会议凋谢能力中反对基于 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 鉴权”章节。

本文由华为云公布

退出移动版