* LCIMClient.cs:
* LCIMSignature.cs: * LCIMConversation.cs: * LCIMSignatureAction.cs: * ILCIMSignatureFactory.cs: * LocalSignatureFactory.cs: * Realtime.csproj: chore: 完善签名逻辑
parent
b0b85274ca
commit
92ee97d236
|
@ -115,8 +115,16 @@ namespace LeanCloud.Realtime {
|
||||||
Cid = Id,
|
Cid = Id,
|
||||||
};
|
};
|
||||||
conv.M.AddRange(clientIds);
|
conv.M.AddRange(clientIds);
|
||||||
// TODO 签名参数
|
// 签名参数
|
||||||
|
if (client.SignatureFactory != null) {
|
||||||
|
LCIMSignature signature = client.SignatureFactory.CreateConversationSignature(Id,
|
||||||
|
client.ClientId,
|
||||||
|
clientIds,
|
||||||
|
LCIMSignatureAction.Invite);
|
||||||
|
conv.S = signature.Signature;
|
||||||
|
conv.T = signature.Timestamp;
|
||||||
|
conv.N = signature.Nonce;
|
||||||
|
}
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Add);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Add);
|
||||||
request.ConvMessage = conv;
|
request.ConvMessage = conv;
|
||||||
GenericCommand response = await client.connection.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
|
@ -138,8 +146,16 @@ namespace LeanCloud.Realtime {
|
||||||
Cid = Id,
|
Cid = Id,
|
||||||
};
|
};
|
||||||
conv.M.AddRange(removeIds);
|
conv.M.AddRange(removeIds);
|
||||||
// TODO 签名参数
|
// 签名参数
|
||||||
|
if (client.SignatureFactory != null) {
|
||||||
|
LCIMSignature signature = client.SignatureFactory.CreateConversationSignature(Id,
|
||||||
|
client.ClientId,
|
||||||
|
removeIds,
|
||||||
|
LCIMSignatureAction.Kick);
|
||||||
|
conv.S = signature.Signature;
|
||||||
|
conv.T = signature.Timestamp;
|
||||||
|
conv.N = signature.Nonce;
|
||||||
|
}
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
||||||
request.ConvMessage = conv;
|
request.ConvMessage = conv;
|
||||||
GenericCommand response = await client.connection.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
|
@ -282,6 +298,15 @@ namespace LeanCloud.Realtime {
|
||||||
SrcCid = Id,
|
SrcCid = Id,
|
||||||
};
|
};
|
||||||
blacklist.ToPids.AddRange(clientIds);
|
blacklist.ToPids.AddRange(clientIds);
|
||||||
|
if (client.SignatureFactory != null) {
|
||||||
|
LCIMSignature signature = client.SignatureFactory.CreateBlacklistSignature(Id,
|
||||||
|
client.ClientId,
|
||||||
|
clientIds,
|
||||||
|
LCIMSignatureAction.ConversationBlockClients);
|
||||||
|
blacklist.S = signature.Signature;
|
||||||
|
blacklist.T = signature.Timestamp;
|
||||||
|
blacklist.N = signature.Nonce;
|
||||||
|
}
|
||||||
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Block);
|
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Block);
|
||||||
request.BlacklistMessage = blacklist;
|
request.BlacklistMessage = blacklist;
|
||||||
GenericCommand response = await client.connection.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
|
@ -296,6 +321,15 @@ namespace LeanCloud.Realtime {
|
||||||
SrcCid = Id,
|
SrcCid = Id,
|
||||||
};
|
};
|
||||||
blacklist.ToPids.AddRange(clientIds);
|
blacklist.ToPids.AddRange(clientIds);
|
||||||
|
if (client.SignatureFactory != null) {
|
||||||
|
LCIMSignature signature = client.SignatureFactory.CreateBlacklistSignature(Id,
|
||||||
|
client.ClientId,
|
||||||
|
clientIds,
|
||||||
|
LCIMSignatureAction.ConversationUnblockClients);
|
||||||
|
blacklist.S = signature.Signature;
|
||||||
|
blacklist.T = signature.Timestamp;
|
||||||
|
blacklist.N = signature.Nonce;
|
||||||
|
}
|
||||||
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Unblock);
|
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Unblock);
|
||||||
request.BlacklistMessage = blacklist;
|
request.BlacklistMessage = blacklist;
|
||||||
GenericCommand response = await client.connection.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
|
@ -467,5 +501,16 @@ namespace LeanCloud.Realtime {
|
||||||
MemberIdList = conv.M.ToList();
|
MemberIdList = conv.M.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void MergeFrom(Dictionary<string, object> conv) {
|
||||||
|
if (conv.TryGetValue("objectId", out object idObj)) {
|
||||||
|
Id = idObj as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conv.TryGetValue("unique", out object uniqueObj)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,13 @@ namespace LeanCloud.Realtime {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LCIMClient(string clientId) {
|
internal ILCIMSignatureFactory SignatureFactory {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCIMClient(string clientId, ILCIMSignatureFactory signatureFactory = null) {
|
||||||
ClientId = clientId;
|
ClientId = clientId;
|
||||||
|
SignatureFactory = signatureFactory;
|
||||||
conversationDict = new Dictionary<string, LCIMConversation>();
|
conversationDict = new Dictionary<string, LCIMConversation>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +100,14 @@ namespace LeanCloud.Realtime {
|
||||||
await connection.Connect();
|
await connection.Connect();
|
||||||
// Open Session
|
// Open Session
|
||||||
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
|
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
|
||||||
request.SessionMessage = new SessionCommand();
|
SessionCommand session = new SessionCommand();
|
||||||
|
if (SignatureFactory != null) {
|
||||||
|
LCIMSignature signature = SignatureFactory.CreateConnectSignature(ClientId);
|
||||||
|
session.S = signature.Signature;
|
||||||
|
session.T = signature.Timestamp;
|
||||||
|
session.N = signature.Nonce;
|
||||||
|
}
|
||||||
|
request.SessionMessage = session;
|
||||||
GenericCommand response = await connection.SendRequest(request);
|
GenericCommand response = await connection.SendRequest(request);
|
||||||
SessionToken = response.SessionMessage.St;
|
SessionToken = response.SessionMessage.St;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +151,7 @@ namespace LeanCloud.Realtime {
|
||||||
bool temporary = false,
|
bool temporary = false,
|
||||||
int temporaryTtl = 86400,
|
int temporaryTtl = 86400,
|
||||||
Dictionary<string, object> properties = null) {
|
Dictionary<string, object> properties = null) {
|
||||||
GenericCommand command = NewCommand(CommandType.Conv, OpType.Start);
|
GenericCommand request = NewCommand(CommandType.Conv, OpType.Start);
|
||||||
ConvCommand conv = new ConvCommand {
|
ConvCommand conv = new ConvCommand {
|
||||||
Transient = transient,
|
Transient = transient,
|
||||||
Unique = unique,
|
Unique = unique,
|
||||||
|
@ -159,8 +171,14 @@ namespace LeanCloud.Realtime {
|
||||||
Data = JsonConvert.SerializeObject(LCEncoder.Encode(properties))
|
Data = JsonConvert.SerializeObject(LCEncoder.Encode(properties))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
command.ConvMessage = conv;
|
if (SignatureFactory != null) {
|
||||||
GenericCommand response = await connection.SendRequest(command);
|
LCIMSignature signature = SignatureFactory.CreateStartConversationSignature(ClientId, members);
|
||||||
|
conv.S = signature.Signature;
|
||||||
|
conv.T = signature.Timestamp;
|
||||||
|
conv.N = signature.Nonce;
|
||||||
|
}
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await connection.SendRequest(request);
|
||||||
string convId = response.ConvMessage.Cid;
|
string convId = response.ConvMessage.Cid;
|
||||||
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
||||||
if (transient) {
|
if (transient) {
|
||||||
|
@ -334,7 +352,7 @@ namespace LeanCloud.Realtime {
|
||||||
OnMessageReceived?.Invoke(null, message);
|
OnMessageReceived?.Invoke(null, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LCIMConversation GetOrCreateConversation(string convId) {
|
internal LCIMConversation GetOrCreateConversation(string convId) {
|
||||||
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
||||||
conversation = new LCIMConversation(this);
|
conversation = new LCIMConversation(this);
|
||||||
conversationDict.Add(convId, conversation);
|
conversationDict.Add(convId, conversation);
|
||||||
|
|
|
@ -19,5 +19,6 @@
|
||||||
<Folder Include="Conversation\" />
|
<Folder Include="Conversation\" />
|
||||||
<Folder Include="Message\" />
|
<Folder Include="Message\" />
|
||||||
<Folder Include="Internal\WebSocket\" />
|
<Folder Include="Internal\WebSocket\" />
|
||||||
|
<Folder Include="Signature\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace LeanCloud.Realtime {
|
||||||
|
public interface ILCIMSignatureFactory {
|
||||||
|
/// <summary>
|
||||||
|
/// 登录签名
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
LCIMSignature CreateConnectSignature(string clientId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建开启对话签名
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
LCIMSignature CreateStartConversationSignature(string clientId, IEnumerable<string> memberIds);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建会话相关签名
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="conversationId"></param>
|
||||||
|
/// <param name="clientId"></param>
|
||||||
|
/// <param name="memberIds"></param>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
LCIMSignature CreateConversationSignature(string conversationId, string clientId, IEnumerable<string> memberIds, string action);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建黑名单相关签名
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="conversationId"></param>
|
||||||
|
/// <param name="clientId"></param>
|
||||||
|
/// <param name="memberIds"></param>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
LCIMSignature CreateBlacklistSignature(string conversationId, string clientId, IEnumerable<string> memberIds, string action);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace LeanCloud.Realtime {
|
||||||
|
public class LCIMSignature {
|
||||||
|
public string Signature {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Timestamp {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Nonce {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCIMSignature() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace LeanCloud.Realtime {
|
||||||
|
public static class LCIMSignatureAction {
|
||||||
|
// 邀请
|
||||||
|
public const string Invite = "invite";
|
||||||
|
// 踢出
|
||||||
|
public const string Kick = "kick";
|
||||||
|
|
||||||
|
//
|
||||||
|
public const string ClientBlockConversations = "client-block-conversations";
|
||||||
|
|
||||||
|
public const string ClientUnblockConversations = "client-unblock-conversations";
|
||||||
|
|
||||||
|
public const string ConversationBlockClients = "conversation-block-clients";
|
||||||
|
|
||||||
|
public const string ConversationUnblockClients = "conversation-unblock-clients";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using LeanCloud.Realtime;
|
||||||
|
using LeanCloud;
|
||||||
|
|
||||||
|
namespace RealtimeConsole {
|
||||||
|
public class LocalSignatureFactory : ILCIMSignatureFactory {
|
||||||
|
const string MasterKey = "pyvbNSh5jXsuFQ3C8EgnIdhw";
|
||||||
|
|
||||||
|
public LCIMSignature CreateConnectSignature(string clientId) {
|
||||||
|
long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
|
string nonce = NewNonce();
|
||||||
|
string signature = GenerateSignature(LCApplication.AppId, clientId, string.Empty, timestamp.ToString(), nonce);
|
||||||
|
return new LCIMSignature {
|
||||||
|
Signature = signature,
|
||||||
|
Timestamp = timestamp,
|
||||||
|
Nonce = nonce
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCIMSignature CreateStartConversationSignature(string clientId, IEnumerable<string> memberIds) {
|
||||||
|
string sortedMemberIds = string.Empty;
|
||||||
|
if (memberIds != null) {
|
||||||
|
List<string> sortedMemberList = memberIds.ToList();
|
||||||
|
sortedMemberList.Sort();
|
||||||
|
sortedMemberIds = string.Join(":", sortedMemberList);
|
||||||
|
}
|
||||||
|
long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
|
string nonce = NewNonce();
|
||||||
|
string signature = GenerateSignature(LCApplication.AppId, clientId, sortedMemberIds, timestamp.ToString(), nonce);
|
||||||
|
return new LCIMSignature {
|
||||||
|
Signature = signature,
|
||||||
|
Timestamp = timestamp,
|
||||||
|
Nonce = nonce
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCIMSignature CreateConversationSignature(string conversationId, string clientId, IEnumerable<string> memberIds, string action) {
|
||||||
|
string sortedMemberIds = string.Empty;
|
||||||
|
if (memberIds != null) {
|
||||||
|
List<string> sortedMemberList = memberIds.ToList();
|
||||||
|
sortedMemberList.Sort();
|
||||||
|
sortedMemberIds = string.Join(":", sortedMemberList);
|
||||||
|
}
|
||||||
|
long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
|
string nonce = NewNonce();
|
||||||
|
string signature = GenerateSignature(LCApplication.AppId, clientId, conversationId, sortedMemberIds, timestamp.ToString(), nonce, action);
|
||||||
|
return new LCIMSignature {
|
||||||
|
Signature = signature,
|
||||||
|
Timestamp = timestamp,
|
||||||
|
Nonce = nonce
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCIMSignature CreateBlacklistSignature(string conversationId, string clientId, IEnumerable<string> memberIds, string action) {
|
||||||
|
string sortedMemberIds = string.Empty;
|
||||||
|
if (memberIds != null) {
|
||||||
|
List<string> sortedMemberList = memberIds.ToList();
|
||||||
|
sortedMemberList.Sort();
|
||||||
|
sortedMemberIds = string.Join(":", sortedMemberList);
|
||||||
|
}
|
||||||
|
long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
|
string nonce = NewNonce();
|
||||||
|
string signature = GenerateSignature(LCApplication.AppId, clientId, conversationId, sortedMemberIds, timestamp.ToString(), nonce, action);
|
||||||
|
return new LCIMSignature {
|
||||||
|
Signature = signature,
|
||||||
|
Timestamp = timestamp,
|
||||||
|
Nonce = nonce
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string SignSHA1(string key, string text) {
|
||||||
|
HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(key));
|
||||||
|
byte[] bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(text));
|
||||||
|
string signature = BitConverter.ToString(bytes).Replace("-", string.Empty);
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NewNonce() {
|
||||||
|
byte[] bytes = new byte[10];
|
||||||
|
using (RandomNumberGenerator generator = RandomNumberGenerator.Create()) {
|
||||||
|
generator.GetBytes(bytes);
|
||||||
|
}
|
||||||
|
return Convert.ToBase64String(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GenerateSignature(params string[] args) {
|
||||||
|
string text = string.Join(":", args);
|
||||||
|
string signature = SignSHA1(MasterKey, text);
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue