ReCAPTCHA经常出现“远程主机强制关闭了一个现有的连接”的错误

4

我在Azure云中托管的MVC4应用程序中使用ReCAPTCHA来为一个只有一个注册表单的简单网站进行保护。目前每小时大约有100-120个成功的注册。问题是,日志中出现了数百个System.Net.Sockets.SocketException: 远程主机强制关闭了一个现有的连接错误,并且这个数字还在迅速增长:

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> 
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> 
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> 
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)     
--- End of inner exception stack trace ---     
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)     
at System.Net.Connection.ReadCallback(IAsyncResult asyncResult)     
--- End of inner exception stack trace ---     
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)     
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)     
--- End of inner exception stack trace ---     
--- End of inner exception stack trace ---     
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)     
at My.Web.Infrastructure.Filters.ValidateReCaptchaAttribute.OnActionExecuting(ActionExecutingContext filterContext) in My.Web\Infrastructure\Filters\ValidateReCaptchaAttribute.cs:line 49  ---> 
(Inner Exception #0) System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> 
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> 
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> 
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host     
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)     
--- End of inner exception stack trace ---

我用以下方法使用属性来验证验证码(删除了一些不重要的细节):

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ValidateReCaptchaAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var formValues = new[]
        {
            new KeyValuePair<string, string>("privatekey", ConfigurationProvider.ReCaptchaPrivateKey), 
            new KeyValuePair<string, string>("remoteip", remoteIp.ToString()),
            new KeyValuePair<string, string>("challenge", challengeField), 
            new KeyValuePair<string, string>("response", responseField)
        };

        try
        {
            using (var client = HttpClientFactory.Create())
            using (var data = new FormUrlEncodedContent(formValues))
            using (var response = client.PostAsync("http://www.google.com/recaptcha/api/verify", data).Result)
            {
                var responseString = response.Content.ReadAsStringAsync().Result;
                if (responseString.StartsWith("true") == false)
                {
                    modelState.AddModelError(string.Empty, DisplayName.Validation_CaptchaMissing);
                }
            }
        }
        catch (Exception ex)
        {
            log4net.LogManager.GetLogger("WebLogger").Error(string.Format("ValidateReCaptcha failed on {0}/{1}. {2}", controller, action, formValuesRaw), ex);
            modelState.AddModelError(string.Empty, DisplayName.Validation_CaptchaMissing);
        }
    }
}

它在var response = client.PostAsync()这一行失败。不是总是这样。我无法在本地重现它。但它几乎对网站的每个用户都会失败 - 有时一次,有时两次,有时更多。最终他们能够注册 - 如我所说,我每小时看到超过100个注册 - 但那导致该小时日志表中出现300-400个错误。我尝试进行注册 - 虽然我百分之百确定我正确输入了验证码,但我仍然收到验证错误。

有任何想法吗?我的验证属性是否正常?还可能有其他原因吗?


我不认为这是一个reCAPTCHA的问题。 - Ramesh Rajendran
我确定这不是 - 我只是用所有细节描述我的问题。就像我说的那样,它在PostAsync() 上失败了 - 你有什么想法为什么会这样? - avs099
1个回答

3
啊!..通过删除

解决了它。
using (var client = HttpClientFactory.Create())

在使用IT技术时,我们通常会涉及到创建单例HttpClient对象。

public class ValidateReCaptchaAttribute : ActionFilterAttribute
{
    private static readonly HttpClient HttpClient = new HttpClient();
    // rest of the code goes here...

正如这篇 Stack Overflow 答案建议的一样


我也遇到了同样的问题,但我已经使用了HttpClient单例(这是微软建议的做法)。 - NathanAldenSr
请问您能否发布一下这个“推荐”的链接? - avs099
这里只是我在5秒钟内找到的一个(还有更多,但我没有收藏它们):http://social.msdn.microsoft.com/Forums/en-US/4e12d8e2-e0bf-4654-ac85-3d49b07b50af/best-practice-usage-of-httpclient-for-rest-calls-maximum-throughput?forum=netfxnetcom - NathanAldenSr
它看起来像是reCAPTCHA有时会无缘无故地拒绝/关闭我的连接。我不得不添加代码,以防万一该服务停止运行,绕过了我的注册表单上的reCAPTCHA验证。 - NathanAldenSr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接