* 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,
|
||||
};
|
||||
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);
|
||||
request.ConvMessage = conv;
|
||||
GenericCommand response = await client.connection.SendRequest(request);
|
||||
|
@ -138,8 +146,16 @@ namespace LeanCloud.Realtime {
|
|||
Cid = Id,
|
||||
};
|
||||
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);
|
||||
request.ConvMessage = conv;
|
||||
GenericCommand response = await client.connection.SendRequest(request);
|
||||
|
@ -282,6 +298,15 @@ namespace LeanCloud.Realtime {
|
|||
SrcCid = Id,
|
||||
};
|
||||
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);
|
||||
request.BlacklistMessage = blacklist;
|
||||
GenericCommand response = await client.connection.SendRequest(request);
|
||||
|
@ -296,6 +321,15 @@ namespace LeanCloud.Realtime {
|
|||
SrcCid = Id,
|
||||
};
|
||||
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);
|
||||
request.BlacklistMessage = blacklist;
|
||||
GenericCommand response = await client.connection.SendRequest(request);
|
||||
|
@ -467,5 +501,16 @@ namespace LeanCloud.Realtime {
|
|||
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;
|
||||
}
|
||||
|
||||
public LCIMClient(string clientId) {
|
||||
internal ILCIMSignatureFactory SignatureFactory {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public LCIMClient(string clientId, ILCIMSignatureFactory signatureFactory = null) {
|
||||
ClientId = clientId;
|
||||
SignatureFactory = signatureFactory;
|
||||
conversationDict = new Dictionary<string, LCIMConversation>();
|
||||
}
|
||||
|
||||
|
@ -95,7 +100,14 @@ namespace LeanCloud.Realtime {
|
|||
await connection.Connect();
|
||||
// Open Session
|
||||
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);
|
||||
SessionToken = response.SessionMessage.St;
|
||||
}
|
||||
|
@ -139,7 +151,7 @@ namespace LeanCloud.Realtime {
|
|||
bool temporary = false,
|
||||
int temporaryTtl = 86400,
|
||||
Dictionary<string, object> properties = null) {
|
||||
GenericCommand command = NewCommand(CommandType.Conv, OpType.Start);
|
||||
GenericCommand request = NewCommand(CommandType.Conv, OpType.Start);
|
||||
ConvCommand conv = new ConvCommand {
|
||||
Transient = transient,
|
||||
Unique = unique,
|
||||
|
@ -159,8 +171,14 @@ namespace LeanCloud.Realtime {
|
|||
Data = JsonConvert.SerializeObject(LCEncoder.Encode(properties))
|
||||
};
|
||||
}
|
||||
command.ConvMessage = conv;
|
||||
GenericCommand response = await connection.SendRequest(command);
|
||||
if (SignatureFactory != null) {
|
||||
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;
|
||||
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
||||
if (transient) {
|
||||
|
@ -334,7 +352,7 @@ namespace LeanCloud.Realtime {
|
|||
OnMessageReceived?.Invoke(null, message);
|
||||
}
|
||||
|
||||
private LCIMConversation GetOrCreateConversation(string convId) {
|
||||
internal LCIMConversation GetOrCreateConversation(string convId) {
|
||||
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
||||
conversation = new LCIMConversation(this);
|
||||
conversationDict.Add(convId, conversation);
|
||||
|
|
|
@ -19,5 +19,6 @@
|
|||
<Folder Include="Conversation\" />
|
||||
<Folder Include="Message\" />
|
||||
<Folder Include="Internal\WebSocket\" />
|
||||
<Folder Include="Signature\" />
|
||||
</ItemGroup>
|
||||
</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