Mã nguồn ví dụ sinh ngẫu nhiên BotDetect ASP CAPTCHA

Ví dụ sinh ngẫu nhiên BotDetect ASP CAPTCHA bao gồm mã nguồn để sinh ngẫu nhiên giá trị của các tham số của Captcha. Sử dụng ngẫu nhiên các giải thuật khác nhau của CAPTCHA và các tham số khác có thể tăng tính bảo mật đáng kể, và đây là cách tốt nhất để tận dụng hết 50 giải thuật khác nhau được cung cấp bởi BotDetect.

Vị trí lưu dự án mẫu

Mặc định, ví dụ mẫu này được cài đặt tại thư mục
c:\Program Files\Lanapsoft\BotDetect\ASP\v2.0\Samples\CaptchaRandomization\.

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

BotDetectRandomDemo.asp

Mã nguồn đầy đủ

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head>
    <title>BotDetect CAPTCHA ASP Randomization Demo - Input 
      Page</title>
    <link type='text/css' rel='Stylesheet' href="FormStyle.css" />
    <script type="text/javascript" src="BotDetectScript.js">
    </script>
  </head>
  <body>
    <form name="SampleForm" id="SampleForm" method="post" 
      action="ProcessFormRandom.asp">
    <fieldset id="SampleFields">
      <legend>Sample input form</legend>
      <div class="input">
        <label for="FirstName">First Name:</label>
        <input name="FirstName" id="FirstName" type="text" 
          class="textbox" value="<%=Request("FirstName") %>" />
      </div>
      <div class="input">
        <label for="LastName">Last Name:</label>
        <input name="LastName" type="text"  id="LastName" 
          class="textbox" value="<%= Request("LastName") %>" />
      </div>
    </fieldset>
    <fieldset id="CaptchaValidation">
      <legend>CAPTCHA Validation</legend>
      <div id="PromptDiv">Retype the code from the picture</div>
      <div id="CaptchaDiv">
        <div id="CaptchaImage">
          <img id="SampleForm_CaptchaImage" src="
            LanapBotDetectHandler.asp?Command=CreateImage" 
            alt='CAPTCHA Code Image' />
        </div>
        <div id="CaptchaIcons">
          <a href="LanapBotDetectHandler.asp?Command=CreateSound" 
            onclick='LBD_LoadSound("SampleForm_SoundPlaceholder", 
            "LanapBotDetectHandler.asp?Command=CreateSound");return 
            false;' title="Speak the code"><img src="speaker.gif" 
            alt="Speak the code" /></a>
          <a href="#" onclick='LBD_ReloadImage(
            "SampleForm_CaptchaImage"); return false;' title="
            Change the code"><img src="reload.gif" alt="
            Change the code" /></a>
          <div id='SampleForm_SoundPlaceholder' class="placeholder">
            &nbsp;</div>
        </div>
      </div>
      <div class="input">
        <label for="CaptchaCode">Code:</label>
        <input name="CaptchaCode" id="CaptchaCode" type="text" 
          class="textbox" onkeyup="this.value = 
            this.value.toLowerCase();" />
      </div>
      <%
      If (Request("WrongCode")<>"") Then
        Response.Write("<div><span id='CodeIncorrectLabel'>Incorrect _
          code</span></div>")
      End If
      %>
      </fieldset>
      <div id="ActionDiv">
        <input type="submit" name="ProcessForm" value="Process Form" 
          id="ProcessForm" />
      </div>
      <div id="Note">
        <span>NOTE: the Trial version will use "LANAP" instead of a 
          random code in 50% of CAPTCHA images.</span>
      </div>
    </form>
  </body>
</html>

Giải thích

Mã nguồn này tương tự như trong Dự án mẫu CAPTCHA, với cùng stylesheet, JavaScript, hình ảnh và âm thanh CAPTCHA. Sự khác nhau duy nhất là thành tố hình ảnh CAPTCHA không truyền vào bất cứ tham số nào trong câu truy vấn vì rằng nó được sinh ngẫu nhiên trong file LanapBotDetectHandler.asp.

ProcessFormRandom.asp

Mã nguồn đầy đủ

<%
  'Captcha validation
  Dim result, codeKey, inputCode
  result = False
  codeKey = "LanapBotDetectCode"
  inputCode = Request("CaptchaCode")

  If (Session(codeKey)<>"") Then
    code = Session(codeKey)
    result = (0 = StrComp(inputCode, code, 1))
    'each Captcha code can only be validated once
    Session(codeKey) = ""
  End If

  If result = False Then
    first_name = Request("FirstName")
    last_name = Request("LastName")
    redirect_url = "BotDetectRandomDemo.asp?FirstName=" + _
      first_name + "&LastName=" + last_name + "&WrongCode=WrongCode"
    Response.Redirect redirect_url
  End If
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
  <title>BotDetect CAPTCHA ASP Randomization Demo - Protected 
    Page</title>
  <link type='text/css' rel='Stylesheet' href="FormStyle.css" />
</head>
<body>
  <form name="form1" method="post" id="form1" action="ProcessForm.asp">
    <fieldset id="Properties">
      <legend>BotDetect CAPTCHA validation passed!</legend>
      <div class="input">
        <label for="FirstName">First Name:</label>
        <input name="FirstName" id="FirstName" type="text" 
          class="textbox" readonly="readonly" 
          value="<% =Request("FirstName") %>" />
      </div>
      <div class="input">
        <label for="LastName">Last Name:</label>
        <input name="LastName" id="LastName" type="text" 
          class="textbox" readonly="readonly" 
          value="<% =Request("LastName") %>" />
      </div>
    </fieldset>
    <div id="ActionDiv">
      <a href="BotDetectRandomDemo.asp">Back to the sample form</a>
    </div>
  </form>
</body>
</html>

Giải thích

Mã nguồn xác thực CAPTCHA không thay đổi khi sinh ngẫu nhiên các thuộc tính, vì vậy giải thích và ghi chú tương tự như Ví dụ mẫu xác thực CAPTCHA.

LanapBotDetectHandler.asp

Mã nguồn đầy đủ

<%
Dim code, codeKey, codeHash, codeHashKey, captchaId, comCaptcha, _ 
  index, appCodeKey, captchaSessionIdKey

'the Captcha code is kept in Session state with this key
codeKey = "LanapBotDetectCode"
codeHashKey = "LanapBotDetectCodeHash"
captchaSessionIdKey = "LanapBotDetectID"

Function createGuid()
  Set TypeLib = Server.CreateObject("Scriptlet.TypeLib")
  tg = TypeLib.Guid
  guid = Left(tg, len(tg)-2)
  set regEx = New RegExp
  regEx.IgnoreCase = False
  regEx.Global = True
  regEx.Pattern = "[{}-]"
  createGuid = regEx.Replace(guid, "")
  Set TypeLib = Nothing
End Function

Function getCaptchaSessionID()
  Dim captchaSessionID
  If (Session(captchaSessionIdKey) <> "") Then
    captchaSessionID = Session(captchaSessionIdKey)
  Else
    captchaSessionID = createGuid()
    Session(captchaSessionIdKey) = captchaSessionID
  End If
  getCaptchaSessionID = captchaSessionID
End Function

'if there are multiple Captchas on tn the site, a Captcha id is 
'required to distinguish between them; otherwise, it can be ignored
captchaId = Request("CaptchaId")
If(captchaId<>"") Then
  codeKey = codeKey & "_" & captchaId
End If

If (Request("Command")="CreateImage") Then
'Captcha image generation

  'create the Captcha component instance
  Set comCaptcha = CreateObject("Lanap.BotDetect")

  'randomize the Captcha image drawing algorithm
  Dim algorithms(5)
  algorithms(0) = 28
  algorithms(1) = 36
  algorithms(2) = 44
  algorithms(3) = 25
  algorithms(4) = 39
  algorithms(5) = 48
  comCaptcha.TextStyle = RandomFromValues(algorithms)
  
  'randomize the Captcha code length
  comCaptcha.CodeLength = RandomFromRange(4, 6)
  
  'set other Captcha properties
  comCaptcha.ImageWidth = 238
  comCaptcha.ImageHeight = 50
  comCaptcha.CodeType = 0
  comCaptcha.Format = "JPEG"

    'set Captcha image Http response headers
  Response.Buffer = True
  Response.CacheControl = "no-cache, no-store, must-revalidate"
  Response.AddHeader "Pragma", "no-cache"
  Response.Expires = -1
  If (comCaptcha.Format="JPEG") Then
    Response.ContentType = "image/jpeg"
  ElseIf (comCaptcha.Format="PNG") Then
    Response.ContentType = "image/png"
  ElseIf (comCaptcha.Format="GIF") Then
    Response.ContentType = "image/gif"
  ElseIf (comCaptcha.Format="BMP") Then
    Response.ContentType = "image/bmp"
  End If

  'generate the Captcha image binary data
  Dim varPicture
  varPicture = comCaptcha.CreateImage

  'save the Captcha code for sound generation and validation
  code = comCaptcha.GetValue
  Session(codeKey) = code
  'save the code hash for backward compatibility with older validation 
  'code
  codeHash = comCaptcha.GetHashValue
  Session(codeHashKey) = codeHash

  'Chrome workaround
  index = InStr(Request.ServerVariables("HTTP_USER_AGENT"), "Chrome")
  If (index > 0) Then
    appCodeKey = getCaptchaSessionID() & codeKey
    Application.Lock
    Application(appCodeKey) = code
    Application.UnLock
    Response.Cookies(captchaSessionIdKey) = getCaptchaSessionID()
    Response.Cookies(captchaSessionIdKey).Expires = DateAdd("H", 1, Now)
    Response.Cookies(captchaSessionIdKey).Path = "/"
  End If

  'send Captcha image binary data to the client
  Response.BinaryWrite varPicture
  Set comCaptcha = Nothing  'dispose of the Captcha component instance
  Response.End
'end Captcha image generation

ElseIf (Request("Command")="CreateSound") Then
'audio Captcha generation

  'create the Captcha component instance
  Set comCaptcha = CreateObject("Lanap.BotDetect")

  'set Http response headers
  If ((Request.ServerVariables("HTTPS")="off") Or Request("e")="") Then
    Response.CacheControl = "no-cache"
    Response.AddHeader "Pragma", "no-cache"
    Response.Expires = -1
  End If
  Response.Buffer = True
  Response.ContentType = "audio/x-wav"
  If (Request("d") = "") Then
  Response.AddHeader "content-disposition", _
    "attachment; filename=captcha.wav"
  End If
  Response.AddHeader "Content-Transfer-Encoding", "binary"
  Response.AddHeader "Connection", "Close"

  'generate the audio Captcha binary data from the saved code
  code = Session(codeKey)
  If (Request("s") <> "") Then  'Chrome workaround
    appCodeKey = Request("s") & codeKey
    code = Application(appCodeKey)
  End If
  varSound = comCaptcha.CreateSoundFromCode(code)

  'send audio Captcha binary data to the client
  Response.BinaryWrite varSound
  Set comCaptcha = Nothing 'dispose of the Captcha component instance
  Response.End
'end audio Captcha generation

ElseIf (Request("Command")="Validate") Then
'Ajax Captcha validation

  Dim result
  result = False

  If (Session(codeKey)<>"") Then
    Dim inputCode
    inputCode = Request("Code")
    code = Session(codeKey)
    result = (0 = StrComp(inputCode, code, 1))
    'Ajax validation shouldn't remove the code if successful, so both 
    'client- and server-side validation can be performed and pass
    If (Not result) Then
      Session(codeKey) = ""
    End If
  End If

  'Http response headers
  Response.Buffer = True
  Response.ContentType = "text/javascript"
  Response.CacheControl = "no-cache, no-store, must-revalidate"
  Response.AddHeader "Pragma", "no-cache"
  Response.Expires = -1
  Response.AddHeader "Connection", "Close"

  'send the JSON validation result to the client
  Response.Write "{ 'result': " & LCase(CStr(result)) & " }"
  Response.End

'end Ajax Captcha validation
End If

'If neither of the above conditions was met
Response.Status = "400 Bad Request"
Response.End

'helper randomization function
Function RandomFromRange(lowerLimit, upperLimit)
  Dim num
  Randomize
  num = CInt((upperlimit - lowerlimit)*Rnd() + lowerlimit) 
  RandomFromRange = num
End Function

Function RandomFromValues(values)
  Dim num
  Randomize
  num = RandomFromRange(0, UBound(values))
  RandomFromValues = values(num)
End Function
%>

Giải thích

Mã nguồn sinh ngẫu nhiên CAPTCHA được viết trong file LanapBotDetectHandler.asp và không để trong mã ASP của trang, bởi vì hình ảnh CAPTCHA có thể được hiển thị nhiều lần. Nói chung, hình ảnh được tải trong các yêu cầu Http từ trang chính, và nhiều trường hợp khác hình ảnh CAPTCHA được truy cập trực tiếp, mà không cần tải lại trang: như khi người sử dụng click vào nút Reload CAPTCHA, bots truy cập vào hình ảnh... Vì chúng ta muốn việc sinh ngẫu nhiên CAPTCHA áp dụng cho mỗi lần hình ảnh CAPTCHA được tạo ra chứ không phải là chỉ khi trang được tải, đoạn mã sinh ngẫu nhiên phải được viết trong mã sinh CAPTCHA.

Trong phiên bản này của file LanapBotDetectHandler.asp, chúng ta không đọc nhiều thuộc tính khác nhau từ tham số của chuỗi truy vấn nhưng chúng ta thiết lập chúng một cách trực tiếp và ngẫu nhiên hoá các giá trị. Độ dài của ký tự CAPTCHA được sinh ngẫu nhiên giữa giá trị nhỏ nhất và giá trị lớn nhất, trong khi các giải thuật sinh hình ảnh CAPTCHA được chọn ngẫu nhiên trong một tập cho trước. Chúng tôi định nghĩa hai hàm chức năng xử lý cho hai trường hợp đó. RandomFromRange(lowerLimit, upperLimit) trả về giá trị ngẫu nhiên từ một khoảng được xác định, trong khi RandomFromValues(values) lấy một mảng các giá trị và chọn ngẫu nhiên.

Bạn có thể sinh ngẫu nhiên bất ký thuộc tính nào 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 là hai thuộc tính có thể tăng khả năng bảo mật của CAPTCHA nhiều nhất khi được ngẫu nhiên hoá. Dành đủ công sức thì mỗi giải thuật vẽ CAPTCHA riêng lẻ có thể bị bẻ gãy theo lý thuết, nhưng nếu bot phải nhận dạng giải thuật được sử dụng cho mọi hình ảnh, nhiệm vụ trở nên khó khăn gấp nhiều lần. Hơn nữa, vài giải thuật sinh CAPTCHA phổ biến đã bị bẻ gãy vì chúng dùng cùng một độ dài của ký tự CAPTCHA – "tìm 5 ký tự trong hình này" thì dễ hơn nhiều so với "tìm một số ký tự chưa biết trong hình này".

BotDetectScript.js

Mã nguồn đầy đủ

function LBD_LoadSound(soundPlaceholderId, soundLink) {
  if(document.getElementById) {
    var i = soundLink.indexOf('&d=');
    if (-1 != i) {
      soundLink = soundLink.substring(0, i);
    }
    soundLink = soundLink + '&d=' + LBD_GetTimestamp();
		
    if ( (-1 == soundLink.indexOf('&e=')) && 
         (document.location.protocol == "https:")) {
      soundLink = soundLink + '&e=1';
    }

    cid = LBD_GetCookie("LanapBotDetectID");
    if (cid) {
      soundLink = soundLink + '&s=' + cid;
    }

    var placeholder = document.getElementById(soundPlaceholderId);
    var objectSrc = "<object id='captchaSound' 
      classid='clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95' 
      height='0' width='0' style='width:0; height:0;'><param 
      name='AutoStart' value='1' /><param name='Volume' value='0' 
      /><param name='PlayCount' value='1' /><param name='FileName' 
      value='" + soundLink + "' /><embed id='captchaSoundEmbed' 
      src='"+ soundLink + "' autoplay='true' hidden='true' 
      volume='100' type='"+ LBD_GetMimeType() +"' 
      style='display:inline;' /></object>";

    placeholder.innerHTML = "";
    placeholder.innerHTML = objectSrc;
  }
}

function LBD_GetTimestamp() {
  var d = new Date();
  var t = d.getTime() + (d.getTimezoneOffset() * 60000);
  return t;
}

function LBD_GetMimeType() {
  var mimeType = "audio/x-wav";
  return mimeType;
}

var LBD_ImgId = null;
var LBD_Img = null;
var LBD_NewImg = null;
var LBD_Parent = null;
var LBD_ImagePrompt = null;

function LBD_ReloadImage(imgId) {
  if(imgId) {
    LBD_ImgId = imgId;
    LBD_Img = document.getElementById(LBD_ImgId);
    var src = LBD_Img.src;

    var i = src.indexOf('&d=');
    if (-1 != i) {
      src = src.substring(0, i);
    }
    var newSrc = src + '&d=' + LBD_GetTimestamp();

    LBD_NewImg = document.createElement('img');
    LBD_NewImg.onload = LBD_ShowImage;
    LBD_NewImg.id = LBD_Img.id;
    LBD_NewImg.alt = LBD_Img.alt;
    LBD_NewImg.src = newSrc;

    LBD_ImagePrompt = document.createElement('span');
    LBD_ImagePrompt.appendChild(document.createTextNode('loading...'));

    LBD_Parent = LBD_Img.parentNode;
    LBD_Parent.removeChild(LBD_Img);
    LBD_Parent.appendChild(LBD_ImagePrompt);
  }
}

function LBD_ShowImage() {
  if(LBD_NewImg && LBD_Parent && LBD_ImagePrompt) {
    LBD_Parent.removeChild(LBD_ImagePrompt);
    LBD_Parent.appendChild(LBD_NewImg);
  }
}

function LBD_GetCookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for(var i=0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1, c.length);
    }
    if (c.indexOf(nameEQ) == 0) {
      return c.substring(nameEQ.length, c.length);
    }
  }
  return null;
}

Giải thích

Không có thay đổi nào trong mã script ở phía máy khách khi sinh ngẫu nhiên các thuộc tính của CAPTCHA, vì tất cả việc sinh ngẫu nhiên được thực hiện trên máy chủ (nếu không thì nó có thể bị bẻ gãy). Vì vậy giải thích và ghi chú tương tự như Mã nguồn ví dụ mẫu xác thực CAPTCHA.

FormStyle.css

Mã nguồn đầy đủ

body {
  background-color: #EEEEFF;
  font-family: Verdana, Arial;
  font-size: 0.9em;
}

fieldset {
  padding: 0 10px 10px 10px;
  margin: 11px;
  width: 300px;
  display: block;
}

div.input {
  margin: 7px 0;
}

legend {
  padding: 5px;
  color: #999999;
}

label {
  display: block;
  width: 85px;
  float: left;
  text-align: right;
  padding-right: 5px;
}

input.textbox {
  width: 170px;
}

input.textboxSmall {
  width: 40px;
}

#CodeIncorrectLabel {
  color: Red;
}

#CodeCorrectLabel {
  color: Green;
}

#Note {
  padding: 0;
  margin: 11px;
  margin-bottom: -7px;
  width: 320px;
  font-size: 0.8em;
  color: Red;
}

#PromptDiv {
  padding: 0;
  margin: 0;
  margin-bottom: 8px;
}

#ActionDiv {
  padding: 0 0 10px 10px;
  margin: 11px;
  margin-right: 0;
  width: 314px;
  text-align:right;
}

fieldset #ActionDiv{
  padding: 0;
  margin: 0;
  width: auto;
  text-align:right;
}

#CaptchaDiv {
  margin: 0;
  padding: 0;
  width:265px;
  height:50px;
  padding-bottom: 5px;
}

#CaptchaImage {
  float: left;
  margin: 0;
  padding: 0;
  width:240px;
  height:50px;
}

#CaptchaIcons {
  width: 22px;
  height: 50px;
  float: right;
  text-align: left;
  margin: 0;
  padding: 0;
}

td#CaptchaIcons {
  padding-left: 3px;
}

#CaptchaIcons img {
  border: 0;
  margin: 0;
  padding: 0;
  padding-bottom: 3px;
}

*html #CaptchaIcons img {
  margin-bottom: -2px;
}

.placeholder {
  visibility: hidden;
  width:0 !important;
  height:0 !important;
}

*html .placeholder {
  display: none !important;
}

#CaptchaPreviewDiv {
  margin: 0;
  padding: 0;
  padding-bottom: 5px;
}

div.FeaturesInput {
  margin: 7px 0;
}

div.FeaturesInput label {
  width: 110px;
}

Giải thích

Định nghĩa style được sử dụng trong ví dụ này giống như trong Mã nguồn ví dụ mẫu xác thực CAPTCHA.

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 CAPTCHA Randomization ASP 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