调用谷歌reCAPTCHA API返回JSON后IIS报循环引用错误如何解决?
问题根因
- 循环引用报错和服务器依赖缺失无关,是代码异常处理逻辑存在缺陷:
catch块直接返回了完整的Exception异常对象,ASP.NET 默认使用的JavaScriptSerializer序列化异常对象时,会因为异常内部存在嵌套循环引用结构(如关联的反射对象、堆栈信息的嵌套关联)触发序列化失败。 - 本地运行正常、生产环境报错的核心原因是:本地网络可以正常访问谷歌reCAPTCHA接口,代码不会进入
catch分支;生产服务器受防火墙规则限制,无法对外访问谷歌API地址,请求抛出异常进入catch分支,才触发了序列化报错。
修复方案
1. 调整后端接口异常返回逻辑
禁止直接返回Exception对象,改为返回无循环引用的自定义结构,修改后的C#代码如下:
[WebMethod] public static async Task<object> Login(string un, string pw, string recap) { try { string key = ConfigurationManager.AppSettings["recap"]; string recaptchaEnc = HttpUtility.UrlEncode(recap); // 建议将HttpClient改为静态单例,避免频繁新建实例导致端口耗尽 using (HttpClient client = new HttpClient()) { var resp = await client.GetStringAsync("https://www.google.com/recaptcha/api/siteverify?secret=" + key + "&response=" + recaptchaEnc).ConfigureAwait(false); return new { isSuccess = true, msg = resp.ToString()}; } } catch (Exception e) { // 仅返回纯文本异常信息,不返回完整异常对象 return new { isSuccess = false, msg = "人机验证请求失败:" + e.Message }; } }
2. 同步调整前端Ajax逻辑适配返回结构
success: function (result) { if (result.d.isSuccess && result.d.msg.toLowerCase().indexOf('success') > -1) { window.location.href = '/AdminPage.aspx'; } else { exeAlert([result.d.msg], 'Error'); } },
3. 处理生产服务器网络问题
- 检查生产服务器出站防火墙规则,确认开放了443端口对reCAPTCHA接口域名的访问权限。
- 如果服务器网络无法访问谷歌服务,可调整网络出站策略,或者替换为符合当前网络环境的人机验证方案。
可选优化项
- 将
HttpClient设置为静态单例复用,避免每次请求新建实例导致的套接字资源耗尽问题。 - 后端拿到reCAPTCHA返回结果后直接反序列化解析校验结果,不要将原始JSON直接返回给前端,降低前端解析出错概率。
内容的提问来源于stack exchange,提问作者Boxcomeaux
相关产品推荐
相关产品推荐

