整个验证过程使用到了SRP6算法.具体实现网上有很多资料.本文只是对验证的流程做个总结.
(2).从数据库获取该用户信息(sha_pass_hash,v,s,last_ip等信息).不存在 sAuthLogonChallenge_S::error = WOW_FAIL_UNKNOWN_ACCOUNT
(3).检查最后登录的ip是否与账户绑定,若已绑定且socket ip与绑定ip不同 sAuthLogonChallenge_S::error = WOW_FAIL_SUSPENDED
(4).检查用户名是否被封,被封sAuthLogonChallenge_S::error = WOW_FAIL_SUSPENDED
(5).使用sha6算法填充sAuthLogonChallenge_S结构.sAuthLogonChallenge_S::error = WOW_SUCCESS
通过以上五部后,服务器将sAuthLogonChallenge_S结构的数据包发送给客户端.
2.客户端通过上述结构体中数据,算出结果发送编号为CMD_AUTH_LOGON_PROOF的数据包,该数据包结构如下:
(1).检查客户端版本是否允许.
(2).使用SRP6计算M值,与客户端发来的M1做对比
(3).M值相同计算sessionkey.写入数据库,以便游戏服务器使用
(4) 发送sAuthLogonProof_S包.
大致为如下几步:
一.服务端通过SRP6算法验证客户端账户合法性
二.客户端账户合法生成SessionKey,告知客户端,服务端写入数据库,供游戏服务器使用.
三.客户端请求游戏服务器列表.服务端将游戏服务器列表发予客户端
typedef struct AUTH_LOGON_CHALLENGE_C
{
// header部分
uint8 cmd; // CMD_AUTH_LOGON_CHALLENGE
uint8 error; //
uint16 size; // body部分长度
// body部分
uint8 gamename[4]; // 游戏名 例如:WoW\0
uint8 version1; // 客户端版本号
uint8 version2;
uint8 version3;
uint16 build;
uint8 platform[4]; // 客户端运行平台 例如:x86\0
uint8 os[4]; // 操作系统 win\0
uint8 country[4]; // 客户端语言 zhTW\0
uint32 timezone_bias;
uint32 ip; // 客户端IP地址
uint8 I_len; // 用户名长度
uint8 I[1]; // 用户名,这是一个数组头指针
} sAuthLogonChallenge_C;服务器收到该数据包后,作如下处理:typedef struct
{
uint8 cmd; // CMD_AUTH_LOGON_CHALLENG
uint8 error; // 结果
uint8 unk2; // 以下成员皆为SHA6算法结果
uint8 B[32];
uint8 g_len;
uint8 g[1];
uint8 N_len;
uint8 N[32];
uint8 s[32];
uint8 unk3[16];
} sAuthLogonChallenge_S; (1).获得客户端ip(从连接套接字获取),从数据库查询,是否被封.被封 sAuthLogonChallenge_S::error = WOW_FAIL_BANNED(2).从数据库获取该用户信息(sha_pass_hash,v,s,last_ip等信息).不存在 sAuthLogonChallenge_S::error = WOW_FAIL_UNKNOWN_ACCOUNT
(3).检查最后登录的ip是否与账户绑定,若已绑定且socket ip与绑定ip不同 sAuthLogonChallenge_S::error = WOW_FAIL_SUSPENDED
(4).检查用户名是否被封,被封sAuthLogonChallenge_S::error = WOW_FAIL_SUSPENDED
(5).使用sha6算法填充sAuthLogonChallenge_S结构.sAuthLogonChallenge_S::error = WOW_SUCCESS
通过以上五部后,服务器将sAuthLogonChallenge_S结构的数据包发送给客户端.
2.客户端通过上述结构体中数据,算出结果发送编号为CMD_AUTH_LOGON_PROOF的数据包,该数据包结构如下:
typedef struct AUTH_LOGON_PROOF_C
{
uint8 cmd; // CMD_AUTH_LOGON_PROOF
uint8 A[32]; // SRP6 A值
uint8 M1[20]; // SRP6 M值,最终比较值
uint8 crc_hash[20];
uint8 number_of_keys;
uint8 securityFlags; // 0x00-0x04
} sAuthLogonProof_C;服务端收到以上包后,作如下处理(1).检查客户端版本是否允许.
(2).使用SRP6计算M值,与客户端发来的M1做对比
(3).M值相同计算sessionkey.写入数据库,以便游戏服务器使用
(4) 发送sAuthLogonProof_S包.
typedef struct AUTH_LOGON_PROOF_S
{
uint8 cmd; // CMD_AUTH_LOGON_PROOF
uint8 error; // 验证成功与否标记
uint8 M2[20]; // 客户端sessionkey
uint32 accountFlags; // 帐号状态标记
uint32 surveyId; // 0
uint16 unkFlags;
} sAuthLogonProof_S;
3.客户端发送编号为CMD_REALM_LIST的数据包,该包为5个字节.
服务端读取realmlist表和realmcharacters表,将游戏服务器列表及账户角色数量发给客户端
本文概述了SRP6算法在客户端身份验证流程中的应用,包括服务端验证客户端账户合法性、生成SessionKey并告知客户端,客户端请求游戏服务器列表的过程。详细解释了客户端与服务端交互的数据包结构及其处理逻辑。
1297

被折叠的 条评论
为什么被折叠?



