rtc
接入鉴权
更新时间:2021/01/07 GMT+08:00
为保证RTC的通信安全,当用户加入频道时,华为云RTC服务需要对其进行接入鉴权。本章节主要介绍华为云RTC接入鉴权的实现原理及鉴权签名的生成方法。
鉴权原理
华为云RTC系统使用数字签名作为接入鉴权方式,需要在相应的SDK的初始化或登录函数中提供“app_id”、“room_id”、“user_id”、“ctime”和“signature”等信息,才能接入华为RTC服务。“signature”为标识签名,由租户使用华为云RTC提供的“app_key”,按照华为RTC的签名算法自行生成。
signature = HMAC256(app_key,(app_id + room_id + user_id +ctime))
- app_key:华为云RTC针对每个app生成的鉴权密钥,需要安全保存,谨防泄漏。
- app_id:华为云RTC生成的应用ID。
- room_id:租户自行创建的房间ID。
- user_id:租户接入华为云RTC系统的用户ID。
- ctime:签名鉴权的过期时间,是系统当前UTC时间(unix时间戳)+鉴权过期时间(推荐2小时),单位为秒。
ctime的为创建时间+过期时间,示例:当前时间为9:00,鉴权过期时间为30分钟,则ctime应该为9:30分。即超过9:30分后,signature签名将失效。
建议租户构建自己的应用签名分发服务器,以防止“app_key”下沉到终端APP的过程中造成不必要的泄漏,鉴权原理如图1所示
签名生成方法
您可以参考如下方法生成对应的签名。
- 将“app_id”、“room_id”,“user_id ”和“ctime”拼接为一个字符串。
1 2
long ctime = System.currentTimeMillis() / 1000 + 60 * 60; //有效时间为1小时,单位是秒 String content = app_id + "+" + room_id + "+" + user_id + "+" + ctime;
- 使用“app_key”,通过HAMC-SHA265方式将字符串“content”进行加密,得到签名字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
String signatureStr = hmacSha(appKey, content, "HmacSHA256"); static String hmacSha(String KEY, String VALUE, String SHA_TYPE) { try { SecretKeySpec signingKey = new SecretKeySpec(KEY.getBytes("UTF-8"), SHA_TYPE); Mac mac = Mac.getInstance(SHA_TYPE); mac.init(signingKey); byte[] rawHmac = mac.doFinal(VALUE.getBytes("UTF-8")); byte[] hexArray = { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' }; byte[] hexChars = new byte[rawHmac.length * 2]; for (int j = 0; j < rawHmac.length; j++) { int v = rawHmac[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } catch (Exception ex) { throw new RuntimeException(ex); } }
签名生成样例
为防止“app_key”密钥泄漏,建议您配置自己的应用签名分发服务器,向服务器传入“app_id”、“room_id”,“user_id ”和“ctime”后,由服务器返回签名。详细代码示例如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | package com.xxx.xxx.utils;
import androidx.annotation.NonNull;
import com.alibaba.fastjson.JSON;
import com.huawei.rtcdemo.Constants;
import java.io.IOException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import okhttp3.Response;
public class SignatureUtil {
private static final String TAG = "SignatureUtil";
public interface onSignatureSuccess {
void onSuccess(String signature);
}
public static void getSignature(String appid, String roomid, String userid, long ctime, String signatureKey, onSignatureSuccess callback) {
if (Constants.RTC_SIGNATURE_USE_LOCAL) {
getSignatureLocal(appid, roomid, userid, ctime, signatureKey, callback);
} else {
getSignatureRemote(appid, roomid, userid, ctime, callback);
}
}
private static void getSignatureLocal(String appid, String roomid, String userid, long ctime, String signatureKey, @NonNull onSignatureSuccess callback) {
String content = appid + "+" + roomid + "+" + userid + "+" + ctime; // here "+" is real char in content.
String signature = SignatureUtil.hmacSha256(signatureKey, content);
callback.onSuccess(signature);
}
private static void getSignatureRemote(String appid, String roomid, String userid, long ctime, @NonNull onSignatureSuccess callback) {
new Thread(new Runnable() {
@Override
public void run() {
HttpUtil httpUtil = new HttpUtil();
String url = Constants.RTC_SIGNATURE_URL + "?appid=" + appid + "&roomid=" + roomid + "&userid=" + userid + "&ctime=" + ctime;
Response response = httpUtil.sendGetMethodWithHead(url, "X-AUTH-TOKEN", Constants.RTC_AUTH_TOKEN);
if (response == null) {
return;
}
if (response.isSuccessful()) {
try {
String json = response.body().string();
String signature = JSON.parseObject(json).getString("signature");
callback.onSuccess(signature);
} catch (IOException e) {
LogUtil.e(TAG, "getSignature failed:" + e.getMessage());
}
} else {
LogUtil.e(TAG, "getSignature failed!");
}
}
}).start();
}
public static String hmacSha256(String KEY, String VALUE) {
return hmacSha(KEY, VALUE, "HmacSHA256");
}
private static String hmacSha(String KEY, String VALUE, String SHA_TYPE) {
try {
SecretKeySpec signingKey = new SecretKeySpec(KEY.getBytes("UTF-8"), SHA_TYPE);
Mac mac = Mac.getInstance(SHA_TYPE);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(VALUE.getBytes("UTF-8"));
byte[] hexArray = {
(byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
(byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
};
byte[] hexChars = new byte[rawHmac.length * 2];
for (int j = 0; j < rawHmac.length; j++) {
int v = rawHmac[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
|
