Google reCaptcha v2 工作不稳定问题排查求助
Google reCAPTCHA 表单提交异常排查求助
从未部署过Google reCAPTCHA,目前遇到两个问题:
- 表单提交时而成功时而失败;
- 未勾选验证码提交失败后,重新勾选验证码仍无法发送邮件。
附上相关代码及报错信息,请求协助排查:
后台代码
protected static string ReCaptcha_Key = "<key>"; protected static string ReCaptcha_Secret = "<key>"; public bool IsReCaptchValid() { var result = false; var captchaResponse = Request.Form["g-recaptcha-response"]; var secretKey = ReCaptcha_Secret; var apiUrl = "https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}"; var requestUri = string.Format(apiUrl, secretKey, captchaResponse); var request = (HttpWebRequest)WebRequest.Create(requestUri); using (WebResponse response = request.GetResponse()) { using (StreamReader stream = new StreamReader(response.GetResponseStream())) { JObject jResponse = JObject.Parse(stream.ReadToEnd()); var isSuccess = jResponse.Value<bool>("success"); result = (isSuccess) ? true : false; } } return result; } protected void btnSend_Click(object sender, EventArgs e) { string Name = txtName.Text; string EmailAddress = txtEmail.Text; string phone = "Number not supplied"; if(txtPhone.Text != "") { phone = txtPhone.Text; } string SendAddress = @"<email address>"; string Subject = "Message from " + Name + " Top Tree Fellas Website"; string Message = Regex.Replace(txtMsg.Text, @"\r\n?|\n", "<br />"); if (String.IsNullOrEmpty(Name) || String.IsNullOrEmpty(EmailAddress) || String.IsNullOrEmpty(Message) || !(IsReCaptchValid())) { lblError.Text = "Please ensure all required fields are filled in."; } else { try { MailMessage msg = new MailMessage(); msg.To.Add(new MailAddress(@"<email address>")); msg.Subject = Subject; msg.From = new MailAddress(SendAddress); msg.IsBodyHtml = true; msg.Body = "<p><strong>Contact Name:</strong> " + Name + "<br />"; msg.Body += "<strong>Email Address:</strong> " + EmailAddress + "<br />"; msg.Body += "<strong>Phone:</strong> " + phone + "<br />"; msg.Body += "<strong>Message:</strong><br />" + Message + "</p>"; msg.ReplyToList.Add(new MailAddress(EmailAddress)); SmtpClient smtpClnt = new SmtpClient("smtp.ionos.co.uk"); smtpClnt.UseDefaultCredentials = false; smtpClnt.Port = 587; smtpClnt.Credentials = new NetworkCredential(@"<email address>", "<password>"); smtpClnt.EnableSsl = true; smtpClnt.Send(msg); lblError.ForeColor = System.Drawing.Color.Green; txtName.Text = ""; txtEmail.Text = ""; txtMsg.Text = ""; txtPhone.Text = ""; Response.Write("<script>alert('Message sent');</script>"); } catch (Exception er) { string er1 = er.Message + "<br />" + er.InnerException; lblError.Text = er1; Response.Write("<script>alert('Something went wrong. Please try again later or call us on: 0<phone number>');</script>"); } } }
页面标记
<script src='https://www.google.com/recaptcha/api.js'></script> <div class="g-recaptcha" data-type="image" data-sitekey="6LfDHwcpAAAAAL71bUOZ4291MqxqDyTfvGbzOMcg"></div> <asp:Button ID="btnSend" runat="server" ValidationGroup="vldContact" Text="Send your message" CssClass="btn btn-danger" OnClick="btnSend_Click" />
Web.config配置
<system.net> <defaultProxy> <proxy usesystemdefault = "false" bypassonlocal="false" proxyaddress="http://ntproxyus.lxa.perfora.net:3128"/> </defaultProxy> </system.net>
报错信息
Failure sending mail. System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) --- End of inner exception stack trace --- at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count) at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.TlsStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Mail.SmtpPooledStream.Dispose(Boolean disposing) at System.IO.Stream.Close() at System.IO.Stream.Dispose() at System.Net.ConnectionPool.Destroy(PooledStream pooledStream) at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse) at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint) at System.Net.Mail.SmtpTransport.GetConnection(ServicePoint servicePoint) at System.Net.Mail.SmtpClient.GetConnection() at System.Net.Mail.SmtpClient.Send(MailMessage message)
排查方向及解决方案
1. reCAPTCHA验证逻辑问题
- 验证码一次性使用问题:Google reCAPTCHA的
g-recaptcha-response是一次性的,提交后立即失效。第一次未勾选提交失败后,页面回发时reCAPTCHA控件不会自动重置,导致第二次勾选后可能仍使用旧的无效响应值。
解决:在后台返回错误提示后,强制重置reCAPTCHA:// 在lblError.Text = "Please ensure all required fields are filled in.";后添加 ScriptManager.RegisterStartupScript(this, GetType(), "resetCaptcha", "grecaptcha.reset();", true); - 验证请求异常处理:当前
IsReCaptchValid()方法未处理网络异常,若请求Google验证接口失败会直接抛出异常,导致表单进入错误分支。
解决:给验证方法添加异常捕获:public bool IsReCaptchValid() { try { var captchaResponse = Request.Form["g-recaptcha-response"]; if(string.IsNullOrEmpty(captchaResponse)) return false; var secretKey = ReCaptcha_Secret; var apiUrl = "https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}"; var requestUri = string.Format(apiUrl, secretKey, captchaResponse); var request = (HttpWebRequest)WebRequest.Create(requestUri); using (WebResponse response = request.GetResponse()) using (StreamReader stream = new StreamReader(response.GetResponseStream())) { JObject jResponse = JObject.Parse(stream.ReadToEnd()); return jResponse.Value<bool>("success"); } } catch(Exception ex) { // 可添加日志记录逻辑 return false; } }
2. SMTP邮件发送异常(报错核心原因)
报错显示连接被主机端软件中止,结合代理配置,重点排查以下几点:
- 代理配置冲突:当前代理可能无法正确连接IONOS的SMTP服务器,尝试绕过代理访问SMTP:
修改Web.config的defaultProxy节点:<defaultProxy> <proxy usesystemdefault = "false" bypassonlocal="false" proxyaddress="http://ntproxyus.lxa.perfora.net:3128"/> <bypasslist> <add address="^https?://smtp\.ionos\.co\.uk$"/> </bypasslist> </defaultProxy> - SSL/TLS版本问题:.NET默认TLS版本可能不被IONOS支持,强制使用TLS 1.2:
在smtpClnt.Send(msg)前添加:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - SMTP连接池问题:连接中止可能是连接池复用异常,禁用连接池:
smtpClnt.ServicePoint.ConnectionLeaseTimeout = 0; smtpClnt.ServicePoint.MaxIdleTime = 0;
3. 表单回发状态问题
确保ASP.NET回发后,reCAPTCHA控件能重新生成有效的响应值,避免旧值残留导致验证失败。
内容的提问来源于stack exchange,提问作者M_Griffiths
相关产品推荐
相关产品推荐

