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

使用 jQuery 和 s3capcha 创建 ASP.NET 验证码

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (9投票s)

2009年8月12日

CPOL

5分钟阅读

viewsIcon

87344

downloadIcon

2320

创建一个 ASP.NET 验证码,该验证码可在 Web Forms 或 AJAX 中使用 s3capcha。

Sceenshot of s3capcha [Asp.net version]

引言

s3capcha 是一种简单实用的验证码,它不创建图像文件。它被制作成一个 jQuery 插件,但作者(www.serie3.info)使用 PHP 编写了它。我发现将其代码转换为 ASP.NET 和 C# 非常容易。PHP 代码非常简单,但使用内联配置不是良好的 OOP 风格。我创建了一个易于配置和在应用程序中使用的结构。由于它不创建任何图像,s3capcha 在创建验证码时会降低服务器负载,并且我们还可以将此验证码用于 AJAX 或 MVC 表单。

s3capcha 的工作原理

s3capcha 使用一个简单的模型来创建验证码

  1. 它会随机化图像的索引。
  2. 为每个索引、图像分配随机数。
  3. 从列表中选择一个随机索引。
  4. 将图像编号放入 session 并将图像列表作为单选按钮发送到客户端;每个单选按钮的值都是一个图像编号。
  5. 如果用户选择的数字与 session 值匹配,则验证成功。

s3capcha 使用 jQuery 将单选按钮转换为可点击的图像列表。

使用代码

s3capcha 类有三个方法,它们都是静态的。为了防止使用服务器内存进行配置,我将所有配置作为静态变量放置,以便可以重用它们。

第一个方法 shuffle 会随机化数组索引并返回结果。

public static List<int> shuffle(List<int> input)
{
    List<int> output = new List<int>();
    Random rnd = new Random();

    int FIndex;
    while (input.Count > 0)
    {
        FIndex = rnd.Next(0, input.Count);
        output.Add(input[FIndex]);
        input.RemoveAt(FIndex);
    }

    input.Clear();
    input = null;
    rnd = null;

    return output;
}

此函数获取输入索引列表并对其进行随机化,然后返回结果。您可以修改此代码以扩展它以随机化任何列表。

在运行验证码之前,需要进行一些配置。原始的 s3capcha 支持两种图像主题,我们需要知道正在使用的主题。有一个 XML 文件用于配置验证码(在 s3capcha 文件夹中)。

<?xml version="1.0" encoding="utf-8" ?>
<s3capcha>
<icons>
<name>apple,cherry,lemon,pear,strawberry</name>
<title>Apple,Cherry,Lemon,Pear,Strawberry</title>
<width>33</width>
<height>33</height>
<ext>jpg</ext>
<folder>fruit</folder>
</icons>
<message>Verify that you are a human not robot, please choose {0}</message>
</s3capcha>

您可以看到可以更改所有验证码字符串,并且没有硬编码的字符串。

name 标签包含将从特定文件夹显示的图像名称。title 标签用于翻译图像;如果您使用英语,则可以使用 name 标签的值,否则可以在此标签中以您的语言放入每个图像名称。

还有额外的图像信息,如 widthheight,以及文件扩展名和文件夹名称。文件夹名称必须存在于 s3capcha 中的 icons 文件夹下。

最后的配置是 message 标签。如果您需要翻译或更改客户端浏览器中显示的文本,可以进行更改。不要删除 {0} 标记。它将被替换为用户必须选择的图像名称。

如果您不想使用 XML 文件,可以使用任何方法加载配置。例如,您可以将值作为 App 变量放在 web.config 中。只需更改加载配置的私有方法 LoadConfig。默认代码将加载 XML 文件。

private static bool LoadConfig()
{
    string FilePath = "~/s3capcha/config.xml";
    FilePath = HttpContext.Current.Server.MapPath(FilePath);
    if (System.IO.File.Exists(FilePath))
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(FilePath);
        string BaseNode = "/s3capcha/icons/";

    XmlNode node = doc.SelectSingleNode(BaseNode + "name");
    IconNames = node.InnerText.Split(new char[] { ',' });

    node = doc.SelectSingleNode(BaseNode + "title");
    IconTitles = node.InnerText.Split(new char[] { ',' });
    ....

如果配置已加载,该函数必须返回 true,否则返回 false

第二个方法是 GetHtmlCodes,它渲染验证码的 HTML 代码。它将使用配置;如果没有配置,它将返回错误。

public static string GetHtmlCodes(string PathTo, out int SessionValue)
{
    bool HasValue = false;
    if (string.IsNullOrEmpty(Message))
        HasValue = LoadConfig();
    else
        HasValue = true;

    if (HasValue)
    {
        Random Rnd = new Random();
        int RandomIndex = Rnd.Next(0,IconNames.Length);

        List<int> values = new List<int>();
        for(int i = 0; i < IconNames.Length;i++)
        values.Add(i);
        values = shuffle(values);

        string WriteThis = "<div class=\"s3capcha\"><p>" + 
        string.Format(Message, "<strong>" + IconTitles[values[RandomIndex]] + 
                      "</strong>") + "</p>";

        int[] RandomValues = new int[IconNames.Length];
        for (int i = 0; i < IconNames.Length; i++)
        {
            RandomValues[i] = Rnd.Next();
            WriteThis += string.Format(RowTemplate,
                IconTitles[values[i]],     RandomValues[i],
                PathTo + "/icons/" + Folder + "/" + 
                IconNames[values[i]] + "." + Extention,
                Width, Height);
        }
        WriteThis += "<div style=\"clear:left\"></div></div>";
        SessionValue = RandomValues[RandomIndex];
        return WriteThis;
    }
    else
    {
        SessionValue = -1;
        return "Invalid data, config file not found";
    }
}

PathTo 是 s3capcha 文件夹的位置。而 out 值是您需要放入 session 的内容。

所有服务器端代码都已完成,我们可以使用 s3capcha.js 文件。如果我们需要在页面中使用验证码,我们需要导入两个 JS 文件:一个是对 jquery.js 的引用(可以从 jQuery 网站下载),另一个是 s3capcha.js。

有两种方法可以使用:AJAX 或 Web Forms。

在 ASP.NET Web Forms 中使用

为了在 Web Forms 中使用,我在 s3capcha 文件夹中创建了一个用户控件,您可以将其直接拖放到页面上,然后可以使用 IsValid 属性来验证表单。

s3capcha.ascx html 代码

<!-- html codes -->
<script language="javascript" type="text/javascript" 
src="<%=ResolveClientUrl("~/s3capcha/s3Capcha.js")%>"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function() {$('#capcha').s3Capcha();});
</script>
<div id="capcha">
<asp:Literal ID="CapchaHTML" runat="server"></asp:Literal>
</div>

我添加了对 s3capcha.js 的引用,但由于寻址问题,我使用了 ResolveClinetUrl,它被更改并返回了相对地址。

Literal 控件将包含 HTML 代码。这是 s3capcha.ascx 的代码隐藏文件。

public void SetIt()
{
    int USessionId;
    CapchaHTML.Text = 
    s3capcha.GetHtmlCodes(ResolveClientUrl("~/s3capcha"),
    out USessionId);
    Session[s3capcha.s3name] = USessionId;
}

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
        SetIt();
}

public bool IsValid
{
    get
    {
        bool res = s3capcha.Verify(Session[s3capcha.s3name], 
        Request.Form[s3capcha.s3name]);
        SetIt();
        return res;
    }
}

SetIt 将获取 HTML 代码并设置 session 值。IsValid 将使用 s3capcha 类的辅助方法 verify,该方法仅测试并比较提交的值和 session 值。

创建一个像 default.aspx 这样的 Web Form,并将其拖放到 s3capcha.ascx;然后在您的 postback 按钮函数中使用 IsValid 来验证用户选项。

在 AJAX 表单中使用

对于 AJAX,我们需要两个 ASP.NET 页面。一个页面用于获取 HTML 内容,另一个页面用于提交表单内容和验证用户输入。

我创建了一个名为 s3capcha.ashx(通用处理程序)的页面,它会在每次请求时返回验证码的 HTML 内容并设置 Session 值。

public void ProcessRequest (HttpContext context) {
    context.Response.ContentType = "text/html";

    int USession;
    context.Response.Write(s3capcha.GetHtmlCodes("../../s3capcha", out USession));
    context.Session[s3capcha.s3name] = USession;

    context.Response.End();
}

另一个通用处理程序是 verify.ashx,它使用了我们用户控件的 IsValid 属性。

public void ProcessRequest(HttpContext context)
{
    context.Response.ContentType = "text/plain";

    if (s3capcha.Verify(context.Session[s3capcha.s3name], 
                      context.Request.Form[s3capcha.s3name]))
        context.Response.Write("Success");
    else
        context.Response.Write("Fail");

    context.Response.End();
}

由于处理程序使用 session 值,我们需要继承 IRequiresSessionState 接口。

在客户端页面中,我们需要在表单中放置验证码的位置。通过 AJAX 请求,我们从 s3capcha.ashx 获取结果并将其添加到此位置。

我的示例页面包含(HTML 内容)

<!-- HTML Codes -->
<form id="form1" action="verify.ashx" method="post">
<div id="capcha"></div>
<p><input type="submit" value="submit" /></p>
</form>

我的表单使用 DIV 标签放置验证码内容。对于 JavaScript 代码

//Javascript codes
var getCapcha = function() {
$.ajax({
url: 's3capcha.ashx',
cache: false,
success: function(data) {
$('#capcha').html(data).s3Capcha();
}
});
};

getCapcha 使用 AJAX GET 请求。此外,由于 jQuery 的 cache 参数在 IE 中有效,我们需要禁用它。

现在我们的表单可以工作了,但如果您需要通过 AJAX 提交,可以使用 jQuery forms 插件。目前,我为这个表单创建了一个简单的 Submit 函数。

//Javascript codes
$(document).ready(function() {
getCapcha();
$("form").bind('submit', function() {
$.ajax({
url: 'verify.ashx',
type: 'POST',
data: { 's3capcha': $("input[name=s3capcha]:checked").val() },
cache: false,
success: function(data) {
alert(data);
getCapcha();
}
});
return false;
});
});

查看数据部分以及我向服务器发送的内容。当我渲染验证码内容时,会创建一个名为 "s3capcha" 的单选按钮。我获取选中项的值并将其发送到 verify.ashx 并获取结果。您可以根据需要使用自己的方法。

下载源代码和示例并使用它。有任何想法吗?请在评论区发布。

历史

  • 2009/08/12
    • 首次发布。
© . All rights reserved.