Mã nguồn ví dụ mẫu BotDetect ASP.NET 1.1 CAPTCHA - VB.NET

Ví dụ mẫu sinh ngẫu nhiên BotDetect ASP.NET CAPTCHA cho bạn thấy việc sinh ngẫu nhiên các tham số của Captcha dễ dàng như thế nào, việc này làm tăng đáng kể tính bảo mật của CAPTCHA và đây là cách tốt nhất để tận dụng hết 50 giải thuật khác nhau của BotDetect.

Vị trí dự án mẫu

Mặc định, dự án mẫu này được cài đặt tại
C:\Program Files\Lanapsoft\BotDetect\ASP.NET 1.1\v2.0\Samples\VBNetBotDetect2RandomDemo\.

Bạn cũng có thể chạy nó từ Start Menu:
Programs > Lanapsoft > BotDetect > ASP.NET 1.1 > v2.0 > Samples > VB.NET BotDetect CAPTCHA Randomization Sample.

Default.aspx

Mã nguồn đầy đủ

<%@ Page Language="vb" AutoEventWireup="false"
  Codebehind="Default.aspx.vb" Inherits="VBNetBotDetectDemo._Default" 
%>

<%@ Register Assembly="Lanap.BotDetect" Namespace="Lanap.BotDetect" 
  TagPrefix="BotDetect" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>BotDetect Demo</title>
    <link type='text/css' rel='Stylesheet' href="StyleSheet.css" />
</head>
<body>
    <form id="form1" runat="server">
    <fieldset id="Preview">
        <legend>
            <span id="PreviewLegend">CAPTCHA Preview</span>
        </legend>
        <div id="PromptDiv">
            <span id="Prompt">Type the characters you see in 
              the picture</span>
        </div>
        <div id="CaptchaDiv">
            <BotDetect:Captcha ID="SampleCaptcha" runat="server" />
        </div>
        <div id="ValidationDiv">
            <asp:TextBox ID="CodeTextBox" runat="server">
            </asp:TextBox>
            <asp:Button ID="ValidateButton" runat="server" />
            <asp:Label ID="MessageCorrectLabel" runat="server">
            </asp:Label>
            <asp:Label ID="MessageIncorrectLabel" runat="server">
            </asp:Label>
        </div>
    </fieldset>
    <div id="Note">
        <span>NOTE: the Trial version will use "LANAP" instead of a 
          random code in 50% of renderings.</span>
    </div>
    </form>
</body>
</html>

Giải thích

Những dòng cần thiết để thêm BotDetect CAPTCHA vào trang ASP.NET được tô đậm. Để sử dụng <BotDetect:Captcha>, trước hết chúng ta phải đăng ký Lanap.BotDetect.dll sử dụng <%@Register %>.

Trang web còn chứa <asp:TextBox> để người dùng nhập câu trả lời, một <asp:Button> để gửi câu trả lời, và một cặp <asp:Label> dùng để hiển thị kết quả xác thực. Phần còn lại của file được sinh ra bởi Visual Studio 2003, hoặc dùng để định nghĩa cách thức sắp xếp và hiển thị của trang.

Không có sự khác biệt nào giữa file .aspx của ví dụ này với file cơ bản, vì tất cả việc sinh ngẫu nhiên đều được thực hiện ở mã xử lý trang.

Default.aspx.vb

Mã nguồn đầy đủ

Public Class _Default
    Inherits System.Web.UI.Page

    #Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub _
        InitializeComponent()
    End Sub
    
    Protected WithEvents MessageCorrectLabel As _
        System.Web.UI.WebControls.Label
				
    Protected WithEvents MessageIncorrectLabel As _
        System.Web.UI.WebControls.Label
				
    Protected WithEvents SampleCaptcha As _
        Lanap.BotDetect.Captcha
				
    Protected WithEvents CodeTextBox As _
        System.Web.UI.WebControls.TextBox
				
    Protected WithEvents ValidateButton As _
        System.Web.UI.WebControls.Button

    'NOTE: The following placeholder declaration is required by 
    'the Web Form Designer. Do not delete or move it.
    Private designerPlaceholderDeclaration As System.Object

    Private Sub Page_Init(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form 
        'Designer. Do not modify it using the code editor.
        InitializeComponent()
    End Sub

    #End Region
		
    Protected Sub Page_Load(ByVal sender As System.Object, 
        ByVal e As System.EventArgs) Handles MyBase.Init
				
        'register CAPTCHA-specific event handler
        AddHandler SampleCaptcha.PreDrawCaptchaImage, 
           AddressOf SampleCaptcha_PreDrawCaptchaImage
    End Sub

    Protected Sub Page_PreRender(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.PreRender

        ' initial page setup
        If (Not IsPostBack) Then

            'set control text
            ValidateButton.Text = "Validate"
            MessageCorrectLabel.Text = "Correct!"
            MessageIncorrectLabel.Text = "Incorrect!"

            'these messages are shown only after validation
            MessageCorrectLabel.Visible = False
            MessageIncorrectLabel.Visible = False
        End If

        ' clear user input on Reload button clicks
        Dim scriptTemplate As String
        scriptTemplate = "<script type='text/javascript'>" & _
          "function LBD_ClearUserInput() {{" & _
          "  var LBD_textBox = document.getElementById('{0}');" & _
          "  if(LBD_textBox) {{" & _
          "    LBD_textBox.value = '';" & _
          "  }}" & _
          "}}" & _
          "LBD_RegisterHandler('PreReloadCaptchaImage', _
            LBD_ClearUserInput);</script>"

        Dim script As String
        script = String.Format(scriptTemplate, CodeTextBox.ClientID)
        If (Not Page.ClientScript.IsStartupScriptRegistered( _
            "CaptchaReloadClearInput")) Then
          Page.ClientScript.RegisterStartupScript(Me.GetType(), _ 
            "CaptchaReloadClearInput", script, True)
        End If
				
        ' automatically lowercase user input							
        CodeTextBox.Attributes.Add("onkeyup", _
            "this.value = this.value.toLowerCase();")

        If (IsPostBack) Then
            'validate the input code, and show the 
            'appropriate message 
            Dim code As String = CodeTextBox.Text.Trim().ToUpper()

            If (SampleCaptcha.Validate(code)) Then
                MessageCorrectLabel.Visible = True
                MessageIncorrectLabel.Visible = False
            Else
                MessageCorrectLabel.Visible = False
                MessageIncorrectLabel.Visible = True
            End If

            'clear previous user code input
            CodeTextBox.Text = ""
        End If

    End Sub

    ' all CAPTCHA randomization should be performed in this event 
    ' handler instead of Page_Load or Page_PreRender, because this 
    ' event is also fired for direct CAPTCHA image requests (which 
    ' skip the page events since the page is never loaded), for 
    ' example when clicking the Reload CAPTCHA button repeatedly
    Protected Sub SampleCaptcha_PreDrawCaptchaImage( _ 
        ByVal sender As System.Object, ByVal e As System.EventArgs)
        
        Dim captcha As ICaptcha = sender
        If (captcha.CaptchaId <> SampleCaptcha.CaptchaId) Then
          Return
        End If

        ' randomize code generation properties
        captcha.CodeType = RandomizationHelper.GetRandomCodeType()
        captcha.CodeLength = _ 
            RandomizationHelper.GetRandomCodeLength(4, 6)

        ' randomize text style
        Dim styles As TextStyleEnum() = { _
            TextStyleEnum.Lego, TextStyleEnum.MeltingHeat, _
            TextStyleEnum.Ghostly, TextStyleEnum.FingerPrints, _
            TextStyleEnum.Graffiti2, TextStyleEnum.Bullets2, _
            TextStyleEnum.CaughtInTheNet2, TextStyleEnum.Collage, _ 
            TextStyleEnum.Chalkboard
        }

        captcha.TextStyle = _ 
            RandomizationHelper.GetRandomTextStyle(styles)

    End Sub

End Class

Giải thích

Trong quá trình Page_Init của trang ASP.NET, chúng ta đăng ký một phương thức xử lý sự kiện đặc biệt được thực thi trước mỗi lần hiển thị hình ảnh CAPTCHA, trong phương thức này chúng ta thực hiện việc sinh ngẫu nhiên. Vì các hình ảnh CAPTCHA được sinh ra và gửi tới máy khách trong một yêu cầu Http tách biệt khỏi yêu cầu tải trang ASP.NET (khi mã này được thực thi), chúng ta thêm phương thức xử lý sự kiện để đảm bảo các tham số của CAPTCHA được sinh ngẫu nhiên mỗi khi nó được vẽ, và không chỉ một lần khi trang được tải.

Điều này là quan trọng vì số lần yêu cầu hình ảnh CAPTCHA không nhất thiết phải bằng số lần tải trang - dễ thấy nhất là khi sử dụng nút Reload CAPTCHA, và khi bots truy cập trực tiếp vào hình ảnh CAPTCHA, hình ảnh CAPTCHA có thể được sinh ra chỉ sau một lần tải của trang (và thực thi hàm Page_PreRender tương ứng).

Trong phương thức Captcha_PreDrawCaptchaImage, đối tượng Captcha được truyền qua tham số sender. Để việc sinh ngẫu nhiên được thực hiện dễ dàng, chúng ta sử dụng lớp RandomizationHelper, cho phép chúng ta lấy giá trị ngẫu nhiên của một tham số cho trước từ một tập hợp các giá trị cho trước (ví dụ như CAPTCHA CodeType), hoặc một khoảng các giá trị (ví dụ như CAPTCHA CodeLength), hay từ một tập các giá trị (như CAPTCHA TextStyle).

Bạn cũng có thể sinh ngẫu nhiên các thông số khác của CAPTCHA với cách tương tự, nhưng giải thuật vẽ CAPTCHA và chiều dài ký tự CAPTCHA sẽ tăng tính bảo mật của CAPTCHA nhiều nhất khi chúng được sinh ngẫu nhiên. Mỗi giải thuật CAPTCHA riêng rẽ có thể bị bẻ gãy (nếu dành đủ công sức), nhưng nếu bot còn phải phân biệt từng giải thuật trong từng ảnh, nhiệm vụ sẽ khó khăn hơn gấp bội. Hơn nữa, nhiều giải thuật CAPTCHA phổ biến đã bị bẻ gãy vì nó dùng chiều dài ký tự cố định – "tìm 5 ký tự trong hình này" thì dễ hơn rất nhiều so với "tìm một số ký tự chưa biết trong hình này".

RandomizationHelper.vb

Mã nguồn đầy đủ

Imports Microsoft.VisualBasic
Imports System.Drawing
Imports Lanap.BotDetect

Public NotInheritable Class RandomizationHelper

    Private Sub New()
        'constructor omitted, static methods only
    End Sub

    ' a single global generator is used for all random numbers
    Private Shared ReadOnly _rand As Random = New Random()

    Public Const DefaultCodeType As CodeTypeEnum = _
        CodeTypeEnum.AlphaNumeric

    Public Shared Function GetRandomCodeType( _
        ByVal ParamArray usedValues As CodeTypeEnum()) As CodeTypeEnum

        Dim codeType As CodeTypeEnum = DefaultCodeType

        If (0 = usedValues.Length) Then
            Dim max As Integer = 
                System.Enum.GetValues(GetType(CodeTypeEnum)).Length
            codeType = CType(_rand.Next(max), CodeTypeEnum)
        ElseIf (1 = usedValues.Length) Then
            codeType = usedValues(0)
        Else
            Dim max As Integer = usedValues.Length
            Dim index As Integer = _rand.Next(max)
            codeType = usedValues(index)
        End If

        Return codeType

    End Function

    Public Const DefaultCodeLength As Integer = 5
    Public Const MinCodeLength As Integer = 1
    Public Const MaxCodeLength As Integer = 15

    Public Shared Function GetRandomCodeLength( _
        Optional ByVal min As Integer = 0, Optional ByVal max As _
            Integer = 0) Integer

        If ((max > MaxCodeLength) OrElse (max < MinCodeLength)) Then
            max = MaxCodeLength
        End If

        If ((min < MinCodeLength) OrElse (min > max)) Then
            min = MinCodeLength
        End If

        Return _rand.Next(min, max + 1)

    End Function

    Public Shared ReadOnly DefaultImageFormat As ImageFormatEnum = _
        ImageFormatEnum.Jpeg

    Public Shared Function GetRandomImageFormat( _
        ByVal ParamArray usedValues As ImageFormatEnum()) As _ 
            ImageFormatEnum

        Dim imageFormat As ImageFormatEnum = DefaultImageFormat

        If (0 = usedValues.Length) Then
            Dim max As Integer = System.Enum.GetValues( _
                GetType(ImageFormatEnum)).Length
            imageFormat = CType(_rand.Next(max), ImageFormatEnum)
        ElseIf (1 = usedValues.Length) Then
            imageFormat = usedValues(0)
        Else
            Dim max As Integer = usedValues.Length
            Dim index As Integer = _rand.Next(max)
            imageFormat = usedValues(index)
        End If

        Return imageFormat

    End Function

    Public Shared ReadOnly DefaultImageSize As Size = New Size(250, 50)
    Public Shared ReadOnly MinImageSize As Size = New Size(50, 40)
    Public Shared ReadOnly MaxImageSize As Size = New Size(500, 200)

    Public Shared Function GetRandomImageSize() As Size
        Return GetRandomImageSize(New Size(0, 0), New Size(0, 0))
    End Function

    Public Shared Function GetRandomImageSize(ByVal maxSize As Size) _
        As Size
        
        Return GetRandomImageSize(New Size(0, 0), maxSize)
    End Function

    Public Shared Function GetRandomImageSize(ByVal minSize As Size, _
        ByVal maxSize As Size) As Size
				
        'determine width
        If ((maxSize.Width > MaxImageSize.Width) OrElse _
            (maxSize.Width < MinImageSize.Width)) Then
            maxSize.Width = MaxImageSize.Width
        End If

        If ((minSize.Width < MinImageSize.Width) OrElse _
            (minSize.Width > maxSize.Width)) Then
            minSize.Width = MinImageSize.Width
        End If
				
        Dim width As Integer = _
            _rand.Next(minSize.Width, maxSize.Width + 1)

        'determine height
        If ((maxSize.Height > MaxImageSize.Height) OrElse _
           (maxSize.Height < MinImageSize.Height)) Then
            maxSize.Height = MaxImageSize.Height
        End If

        If ((minSize.Height < MinImageSize.Height) OrElse _
            (minSize.Height > maxSize.Height)) Then
            minSize.Height = MinImageSize.Height
        End If
				
        Dim height As Integer = _
            _rand.Next(minSize.Height, maxSize.Height + 1)

        'the result
        Return New Size(width, height)
    End Function

    Public Const DefaultTextStyle As TextStyleEnum = _
        TextStyleEnum.Chalkboard

    Public Shared Function GetRandomTextStyle( _
        ByVal ParamArray usedValues As TextStyleEnum()) As _
        TextStyleEnum

        Dim textStyle As TextStyleEnum = DefaultTextStyle

        If (0 = usedValues.Length) Then
            Dim max As Integer = _ 
                System.Enum.GetValues(GetType(TextStyleEnum)).Length
            textStyle = CType(_rand.Next(max), TextStyleEnum)
        ElseIf (1 = usedValues.Length) Then
            textStyle = usedValues(0)
        Else
            Dim max As Integer = usedValues.Length
            Dim index As Integer = _rand.Next(max)
            textStyle = usedValues(index)
        End If

        Return textStyle

    End Function

End Class

Giải thích

RandomizationHelper là một lớp tiện ích nhỏ bạn có thể sử dụng trong dự án của bạn để đơn giản hoá việc sinh ngẫu nhiên nhiều tham số khác nhau của CAPTCHA.

Các tham số CAPTCHA lấy các giá trị là số hoặc tập hợp, lớp này cung cấp phương thức trả về giá trị ngẫu nhiên. Mỗi tham số có một giá trị mặc định, và các tham số dạng số có giá trị nhỏ nhất và lớn nhất được định nghĩa trước.

Tất cả các phương thức sinh ngẫu nhiên dùng nhiều tham số khác nhau, thông qua phương thức overloads hoặc từ khoá params.

Phương thức trả về giá trị số (ví dụ, CodeLength) hoạt động như sau:

  • Nếu không có tham số nào được truyền, giá trị ngẫu nhiên được chọn giữa giá trị nhỏ nhất và giá trị lớn nhất định nghĩa trước.
  • Nếu một giá trị được truyền, giá trị ngẫu nhiên được chọn giữa giá trị nhỏ nhất định nghĩa trước và giá trị truyền vào như là giá trị lớn nhất. Chú ý rằng giá trị truyền vào phải nhỏ hơn giá trị lớn nhất được định nghĩa trước.
  • If two values are given as parameters, the random value is selected between the first value as the minimum and the second value as the maximum. Chú ý rằng giá trị nhỏ nhất được truyền vào phải lớn hơn giá trị nhỏ nhất được định nghĩa trước, và giá trị lớn nhất truyền vào phải nhỏ hơn giá trị lớn nhất được định nghĩa trước.

Phương thức trả về giá trị trong tập hợp (ví dụ, CodeType) hoạt động như sau:

  • Nếu không có tham số nào được truyền, giá trị ngẫu nhiên được chọn từ các giá trị có thể.
  • Nếu một giá trị được truyền, nó được trả về như là kết quả - khi bạn truyền vào một giá trị thì sẽ không có sự ngẫu nhiên hoá nào cả. Và nếu bạn muốn dùng một giá trị thì chỉ việc gán trực tiếp vào tham số.
  • Nếu một tập hợp (ví dụ như mảng) các giá trị được truyền, giá trị ngẫu nhiên được chọn trong tập hợp đó.

Dĩ nhiên là bạn có thể sử dụng mã này trực tiếp trong dự án của bạn nhưng đóng gói nó trong lớp RandomizationHelper làm việc đọc mã nguồn dễ dàng hơn và tăng tính tái sử dụng.

Web.config

Mã nguồn đầy đủ

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
  <system.web>
  
  <httpHandlers>
    <add verb="*" path="LanapCaptcha.aspx" 
      type="Lanap.BotDetect.CaptchaHandler, Lanap.BotDetect"/>
  </httpHandlers>

  <!--  DYNAMIC DEBUG COMPILATION
    Set compilation debug="true" to enable ASPX debugging. Otherwise, 
    setting this value to false will improve runtime performance of 
    this application. Set compilation debug="true" to insert debugging 
    symbols (.pdb information) into the compiled page. Because this 
    creates a larger file that executes more slowly, you should set 
    this value to true only when debugging and to false at all other 
    times. For more information, refer to the documentation about 
    debugging ASP.NET files.
  -->
  <compilation 
    defaultLanguage="vb"
    debug="false"
  />

  <!--  CUSTOM ERROR MESSAGES
    Set customErrors mode="On" or "RemoteOnly" to enable custom error 
    messages, "Off" to disable. 
		
    Add <error> tags for each of the errors you want to handle.

    "On" Always display custom (friendly) messages.
		
    "Off" Always display detailed ASP.NET error information.
		
    "RemoteOnly" Display custom (friendly) messages only to users not 
      running on the local Web server. This setting is recommended for 
      security purposes, so that you do not display application detail 
      information to remote clients.
  -->
  <customErrors 
    mode="RemoteOnly" 
  /> 

  <!--  AUTHENTICATION 
    This section sets the authentication policies of the application. 
    Possible modes are "Windows", "Forms", "Passport" and "None".

    "None" No authentication is performed. 
		
    "Windows" IIS performs authentication (Basic, Digest, or 
    Integrated Windows) according to its settings for the 
    application. Anonymous access must be disabled in IIS. 
		
    "Forms" You provide a custom form (Web page) for users to 
    enter their credentials, and then you authenticate them 
    in your application. A user credential token is stored 
    in a cookie.
		
    "Passport" Authentication is performed via a centralized 
    authentication service provided by Microsoft that offers 
    a single logon and core profile services for member sites.
  -->
  <authentication mode="Windows" /> 

  <!--  AUTHORIZATION 
    This section sets the authorization policies of the 
    application. You can allow or deny access to application 
    resources by user or role. Wildcards: "*" mean everyone, 
    "?" means anonymous (unauthenticated) users.
  -->

  <authorization>
    <allow users="*" /> <!-- Allow all users -->
    <!-- 
    <allow users="[comma separated list of users]"
      roles="[comma separated list of roles]"/>
    <deny users="[comma separated list of users]"
      roles="[comma separated list of roles]"/>
    -->
  </authorization>

  <!--  APPLICATION-LEVEL TRACE LOGGING
    Application-level tracing enables trace log output for 
    every page within an application. 
    Set trace enabled="true" to enable application trace 
    logging. If pageOutput="true", the trace information 
    will be displayed at the bottom of each page. Otherwise, 
    you can view the application trace log by browsing the 
    "trace.axd" page from your web application root. 
  -->
  <trace
    enabled="false"
    requestLimit="10"
    pageOutput="false"
    traceMode="SortByTime"
    localOnly="true"
  />

  <!--  SESSION STATE SETTINGS
    By default ASP.NET uses cookies to identify which requests 
    belong to a particular session. If cookies are not available, 
    a session can be tracked by adding a session identifier to the 
    URL. To disable cookies, set sessionState cookieless="true".
  -->
  <sessionState 
    mode="InProc"
    stateConnectionString="tcpip=127.0.0.1:42424"
    sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
    cookieless="false" 
    timeout="20" 
  />

  <!--  GLOBALIZATION
    This section sets the globalization settings of the application. 
  -->
  <globalization 
    requestEncoding="utf-8" 
    responseEncoding="utf-8" 
  />
   
 </system.web>

</configuration>

Giải thích

Những dòng cần thiết để BotDetect CAPTCHA hoạt động đúng được tô đậm, những dòng khác là giá trị chuẩn được sinh ra bởi Visual Studio 2003. Không có thiết lập đặc biệt nào liên quan đến sinh ngẫu nhiên CAPTCHA trong file web.config.

Thành tố <httpHandlers> đăng ký đường dẫn sử dụng cho hình ảnh và âm thanh CAPTCHA được xử lý bởi Lanap.BotDetect.dll code. Thành tố <system.webServer> được sử dụng với cùng mục đích, nhưng chỉ được sử dụng cho IIS 7.0.

Khai báo validateIntegratedModeConfiguration="false" đảm bảo rằng file web.config có thể được xử lý bởi phiên bản cũ hơn của IIS (5.1, 6.0) cũng như phiên bản 7.0. Vì cú pháp đăng ký HttpHandler khác nhau giữa các phiên bản IIS và chế độ tích hợp ASP.NET, dùng cả hai thành tố trên giúp cho file web.config tương thích với tất cả các phiên bản IIS được hỗ trợ.

Thành tố <sessionState> khai báo cơ chế lưu trữ được sử dụng bởi BotDetect để lưu mã CAPTCHA và thiết lập cho mỗi người dùng. Thuộc tính Session State modes, providers, timeouts và cookieless attribute có thể được sử dụng, nhưng thành tố sessionIDManagerType được sử dụng để sửa lỗi gây bởi Windows Media Player 11 khi yêu cầu âm thanh CAPTCHAs (như được giải thích trong mục hỏi đáp).

Phiên bản hiện tại của BotDetect

Xin lưu ý

Trang này là bản dịch tiếng Việt không chính thức của trang gốc tiếng Anh: BotDetect ASP.NET 1.1 CAPTCHA Randomization VB.NET Code Sample và có thể không chính xác, không đầy đủ hoặc không cập nhật.

Cập nhật ngày 2009-11-30. Áp dụng cho BotDetect ASP.NET CAPTCHA v2.0.15 và BotDetect ASP CAPTCHA v2.0.9.

language: English Español Tiếng Việt