如何在Razor Pages中跨请求保留WTelegram.Client实例?
解决WTelegram.Client跨请求保留及登录流程问题
为什么直接序列化WTelegram.Client会失败
WTelegram.Client内部包含TcpFactory这类负责网络连接的底层对象,这类对象关联着socket等系统资源,本身不支持JSON序列化,所以直接把整个Client实例存入Session必然触发序列化错误。
正确的跨请求保留登录状态的方式
不要存储整个Client实例,而是提取登录流程中可序列化的关键状态数据,比如:
- 手机号
- 验证码哈希值(
phone_code_hash) - Base64编码的认证密钥(
auth_key) - 数据中心ID(dc id)
修改后的代码示例
请求验证码的处理方法
public async Task<IActionResult> OnPostCodeAsync() { var wClient = new Client(Config, store); // 触发登录流程,获取验证码发送状态 await wClient.Login(PhoneNumber); // 提取可序列化的登录状态 var loginState = new { PhoneNumber = PhoneNumber, PhoneCodeHash = wClient.PhoneCodeHash, AuthKey = Convert.ToBase64String(wClient.AuthKey), DcId = wClient.Session.DC }; // 将状态序列化后存入Session HttpContext.Session.SetString(telSession, JsonSerializer.Serialize(loginState)); Msg = "验证码已发送至您的手机"; return Page(); }
验证验证码的处理方法
public async Task<IActionResult> OnPostVerifyAsync() { var stateJson = HttpContext.Session.GetString(telSession); if (string.IsNullOrEmpty(stateJson)) { Msg = "请先请求验证码"; return Page(); } var loginState = JsonSerializer.Deserialize<dynamic>(stateJson); // 重新创建Client实例并恢复状态 var wClient = new Client(Config, store); // 恢复认证密钥 wClient.AuthKey = Convert.FromBase64String(loginState.AuthKey); // 设置数据中心信息 await wClient.Session.SetDC(loginState.DcId, wClient.Session.ServerAddress, wClient.Session.Port); // 恢复手机号和验证码哈希 wClient.PhoneNumber = loginState.PhoneNumber; wClient.PhoneCodeHash = loginState.PhoneCodeHash; // 提交验证码完成登录 var loggedUser = await wClient.Login(VerificationCode); Msg = $"登录成功,欢迎 {loggedUser.FirstName}"; // 登录完成后清理Session中的临时状态 HttpContext.Session.Remove(telSession); return Page(); }
用简单类型属性继续登录流程的要点
核心是只保留登录流程必需的、可序列化的简单类型数据:
- 字符串类型:手机号、验证码哈希(
phone_code_hash)、Base64编码的认证密钥 - 整数类型:数据中心ID(dc id)
具体流程:
- 首次请求(获取验证码):创建Client实例,执行登录第一步,提取上述简单类型状态存入Session
- 二次请求(验证验证码):从Session读取状态,创建新的Client实例,恢复状态后执行登录第二步(提交验证码)
注:WTelegram.Client的具体属性名称可参考其源码或官方文档确认,确保PhoneCodeHash、AuthKey等属性可直接调用。
内容的提问来源于stack exchange,提问作者Hamid Z
相关产品推荐
相关产品推荐

