云通信IM的前身是QQ,我们抽离QQ的核心模块,将其整合成适合各终端接入的 IM SDK以及后台服务。
如同QQ一样,云通信IM的核心功能是用来收发消息,但前提是用户必须先登录才能使用。登录QQ用的是QQ号和密码,登录云通信IM则是用用户名 UserID 和密码 UserSig
UserID: 也称为identifier, 用户登录云通信IM时使用的用户名
UserSig: 用户登录云通信IM时使用的密码,本质上是将UserID等信息加密过后得到的密文
这里有三种角色:
云通信IM后台:腾讯云云通信IM的服务端后台
开发者后台:开发者的服务端后台
开发者应用:开发者使用IMSDK开发的给用户使用的终端
1. 用户的APP带上UserID请求开发者后台,请求UserSig
2. 开发者后台使用云通信IM的UserSig生成库,生成UserSig并返回给应用
3. 应用使用UserID和UserSig访问云通信IM后台进行登录
(登录成功后,UserSig会储存在开发者应用的内存里)
通过登录三步,成功登录后,应用将收到云通信IM返回的此用户在云通信IM应用登录成功的凭证(我们称为票据),凭证会存储在开发者应用本地,之后使用云通信IM的提供的核心功能时,云通信IM后台将根据凭证进行鉴权。
有两种方式:
1. 开发者应用本地生成
2. 开发者后台生成
其中,不推荐开发者应用本地生成的方式,原因是客户端代码容易被反编译导致密钥泄露,攻击者将可以使用密钥生成UserSig,成功登录盗用开发者的腾讯云流量。
因此推荐使用开发者后台生成UserSig, 服务器的攻击成本更高,用此种方式将能更好保护开发者的密钥。
在开发者后台,实际上调用云通信IM生成UserSig的库,把以下三个重要信息进行对称加密(非对称的方式已经停用),生成UserSig
SdkAppid:云通信IM应用的唯一ID
SecretKey:云通信IM应用的唯一密钥
ExpireTime:密码过期时间,开发者指定
算法实现源码: JAVA - https://github.com/tencentyun/tls-sig-api-v2-java/blob/master/src/main/java/com/tencentyun/TLSSigAPIv2.java
GO - https://github.com/tencentyun/tls-sig-api-v2-golang/blob/master/tencentyun/TLSSigAPI.go
PHP - https://github.com/tencentyun/tls-sig-api-v2-php/blob/master/src/TLSSigAPIv2.php
Nodejs - https://github.com/tencentyun/tls-sig-api-v2-node/blob/master/TLSSigAPIv2.js
Python - https://github.com/tencentyun/tls-sig-api-v2-python/blob/master/TLSSigAPIv2.py
C# - https://github.com/tencentyun/tls-sig-api-v2-cs/blob/master/tls-sig-api-v2-cs/TLSSigAPIv2.cs
C++ - https://github.com/tencentyun/tls-sig-api-v2-cpp
java源码片段:
GenTLSSignature方法:将信息摘要,使用hmacsha256方法生成UserSig,压缩
hmacsha256方法:调用标准库里的hmac方法进行加密
private static String GenTLSSignature(long sdkappid, String userId, long expire, byte[] userbuf, String priKeyContent) {
if (TextUtils.isEmpty(priKeyContent)) {
return "";
}
long currTime = System.currentTimeMillis() / 1000;
JSONObject sigDoc = new JSONObject();
try {
sigDoc.put("TLS.ver", "2.0");
sigDoc.put("TLS.identifier", userId);
sigDoc.put("TLS.sdkappid", sdkappid);
sigDoc.put("TLS.expire", expire);
sigDoc.put("TLS.time", currTime);
} catch (JSONException e) {
e.printStackTrace();
}
String base64UserBuf = null;
if (null != userbuf) {
base64UserBuf = Base64.encodeToString(userbuf, Base64.NO_WRAP);
try {
sigDoc.put("TLS.userbuf", base64UserBuf);
} catch (JSONException e) {
e.printStackTrace();
}
}
String sig = hmacsha256(sdkappid, userId, currTime, expire, priKeyContent, base64UserBuf);
if (sig.length() == 0) {
return "";
}
try {
sigDoc.put("TLS.sig", sig);
} catch (JSONException e) {
e.printStackTrace();
}
Deflater compressor = new Deflater();
compressor.setInput(sigDoc.toString().getBytes(Charset.forName("UTF-8")));
compressor.finish();
byte[] compressedBytes = new byte[2048];
int compressedBytesLength = compressor.deflate(compressedBytes);
compressor.end();
return new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength)));
}
private static String hmacsha256(long sdkappid, String userId, long currTime, long expire, String priKeyContent, String base64Userbuf) {
String contentToBeSigned = "TLS.identifier:" + userId + "\n"
+ "TLS.sdkappid:" + sdkappid + "\n"
+ "TLS.time:" + currTime + "\n"
+ "TLS.expire:" + expire + "\n";
if (null != base64Userbuf) {
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
}
try {
byte[] byteKey = priKeyContent.getBytes("UTF-8");
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
hmac.init(keySpec);
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes("UTF-8"));
return new String(Base64.encode(byteSig, Base64.NO_WRAP));
} catch (UnsupportedEncodingException e) {
return "";
} catch (NoSuchAlgorithmException e) {
return "";
} catch (InvalidKeyException e) {
return "";
}
}
引入上述的库后,开发者后台调用TLSSigAPIv2的类方法genSig生成UserSig,java代码举例:
public class UserSigSerivce {
private long sdkAppid;
private String secretKey;
private long expire = 60*60*27*7; //开发者自定过期时间,比如7天
public String generateUserSig(String userid){
TLSSigAPIv2 api = new TLSSigApiv2(sdkAppid, secretKey);
return api.genSig(userid, expire)
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。