65.9K
CodeProject 正在变化。 阅读更多。
Home

自定义 reCaptcha 验证

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (20投票s)

2010年10月7日

CPOL

2分钟阅读

viewsIcon

91726

downloadIcon

3004

如何手动将 reCaptcha 集成到您的网站中。

引言

reCaptcha 是一个非常有用的 Captcha 工具,用于验证访问您网站的访问者是否真的是人类。这主要用于防止垃圾邮件。

这是一个示例 reCaptcha

a sample captcha

CodeProject 上有很多自定义 Captcha 解决方案,但 reCaptcha 有一些优势

  • 它由 Google 维护 - 因此,如果 captcha 图像被攻破,Google 的更新将解决问题,而无需 Web 开发人员进行任何工作。
  • reCAPTCHA 挑战的答案被用于数字化文本文档。
  • 您的 Web 服务器不必花费处理器时间来生成 captcha 图像。
  • reCaptcha 有一个音频选项,对视力障碍用户很有用。

这些优点都不错,除非您不喜欢 Google。

背景

在为我的网站开发新功能时,我在实现 reCaptcha 时遇到了一些问题。

提供了一个 .NET 服务器控件,但是,我无法让客户端脚本选择我想要使用的主题,所以我决定坚持下去并自己实现它。

Using the Code

注意 - reCaptcha 要求您创建加密密钥。这些密钥用于提高安全性并且易于创建 - 只需 点击此处创建您的密钥,然后将您的密钥添加到演示的 web.config 中。

首先,我们需要设置客户端。

在页面的头部包含 reCaptcha 客户端库

<head>
    <script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js">
    </script>
</head>     

接下来,添加以下代码

<div id="recaptcha_div"></div>
<script type="text/javascript">
    Recaptcha.create("<%=Config.PublicKey %>",
        "recaptcha_div", {
        lang: "<%=LanguageCode %>",
        theme: "clean",
        callback: Recaptcha.focus_response_field
    });
</script>

如您所见,我们从服务器获取两个值,并直接将其注入到客户端

  1. Config.PublicKey (这是您的公共 reCaptcha 密钥 - 如果您没有密钥,请前往 此处 获取一个。)
  2. LanguageCode

如果您想更改 captcha 使用的主题,可以阅读更多信息 此处

接下来,服务器端代码。

文章下载包含完整的服务器端代码,在这里我将只概述重要的部分。

将自定义验证器添加到您的页面,并提供以下代码作为其服务器端验证方法

// our custom server validator's validation method
protected void OnRecaptchaValidate(object sender, ServerValidateEventArgs e)
{
    string challenge = Request.Form["recaptcha_challenge_field"];
    string clientResponse = Request.Form["recaptcha_response_field"];
    
    reCaptchaValidation validator = 
        new reCaptchaValidation(
                    Config.Proxy,       // if you don't require a proxy to access 
                // the internet, just comment out this line.
                    Request.UserHostAddress, 
                    Config.PrivateKey, 
                    challenge, 
                    clientResponse);
                    
    e.IsValid = validator.Validate();
    
    if (!e.IsValid)
    {
        if (validator.IsErrored)
        {
            // oh dear, something not right
            
            if (validator.Exception != null)        // an exception occurred while 
                        // trying to validate
                Outcome.Text = validator.Exception.ToString();
            else if (validator.ValidationResult != null)  // the validation web service 
                        // returned an error code 
                    // (other than an invalid captcha solution)
                Outcome.Text = "web service error: " + validator.ValidationResult;
        }
    }
}

验证被封装在一个名为 reCaptchaValidation 的类中

public class reCaptchaValidation
{
    private string challenge, response, privateKey, ip;
    private IWebProxy proxy;

    public reCaptchaValidation(string clientIP, string privateKey, 
    string challenge, string response) : this(null, clientIP, privateKey, 
    challenge, response) { }

    public reCaptchaValidation(IWebProxy proxy, string clientIP, 
        string privateKey, string challenge, string response)
    {
        this.proxy = proxy;
        this.ip = clientIP;
        this.privateKey = privateKey;
        this.challenge = challenge;
        this.response = response;
    }

    private bool _errored;
    public bool IsErrored
    {
        get
        {
            return _errored;
        }
    }

    private Exception _ex;
    public Exception Exception
    {
        get
        {
            return _ex;
        }
    }

    private string _vr;
    public string ValidationResult
    {
        get
        {
            return _vr;
        }
    }

    public bool Validate()
    {
        try
        {
            string post = "privatekey=" + HttpUtility.UrlEncode(privateKey) + 
        "&remoteip=" + HttpUtility.UrlEncode(ip) + "&challenge=" + 
        HttpUtility.UrlEncode(challenge) + "&response=" + 
        HttpUtility.UrlEncode(response);

            WebRequest wr = HttpWebRequest.Create
            ("http://www.google.com/recaptcha/api/verify");
            wr.Method = "POST";

            if (proxy != null)
                wr.Proxy = proxy;

            wr.ContentLength = post.Length;
            wr.ContentType = "application/x-www-form-urlencoded";
            using (StreamWriter sw = new StreamWriter(wr.GetRequestStream()))
            {
                sw.Write(post);
                sw.Close();
            }

            HttpWebResponse resp = (HttpWebResponse)wr.GetResponse();
            using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
            {
                string valid = sr.ReadLine();
                if (valid != null)
                {
                    if (valid.ToLower().Trim() == "false")
                    {
                        string errorcode = sr.ReadLine();

                        if (errorcode != null)
                        {
                            if (errorcode.ToLower().Trim() != "incorrect-captcha-sol")
                            {
                                _vr = errorcode;
                                _errored = true;
                                return false;
                            }
                        }
                    }

                    return (valid.ToLower().Trim() == "true");
                }
                else _vr = "empty web service response";

                sr.Close();
                return false;
            }
        }
        catch (Exception caught)
        {
            _errored = true;
            _ex = caught;
        }
        return false;
    }
}

该类通过将所有必需的信息发布到 Google reCAPTCHA 验证 Web 服务来处理用户 captcha 响应的验证。

我使演示 Web 应用程序尽可能易于使用 - 只需在 web.config 中提供所需的值即可。

历史

  • 2010 年 10 月 7 日:发布。
© . All rights reserved.