This is a migrated thread and some comments may be shown as answers.

CaptchaImage-CharSet; back button

16 Answers 257 Views
Captcha
This is a migrated thread and some comments may be shown as answers.
Kamil Zmeskal
Top achievements
Rank 1
Kamil Zmeskal asked on 16 May 2010, 09:36 PM
Hi,

I have two issues:
- I set CaptchaImage-CharSet to "ABCDEFGHJKLMNPQRSTUVWXYZ123456789" but Captcha still generate "O" character. See sample.png.
- when I enter valid code and I go back in the browser then captcha image is still valid with same code - I can valid code only first time and send control to robot (when robot simulate go back then I needn't enter new code).

Can you help me please?

ASP.NET AJAX Q1 2010 SP1

Kamil

16 Answers, 1 is accepted

Sort by
0
Pero
Telerik team
answered on 19 May 2010, 01:17 PM
Hi Kamil,

Straight to the issues:

  • Besides setting the CaptchaImage-CharSet, the CaptchaImage-TextChars property must be set to "CustomCharSet". Here is an example:
    <telerik:RadCaptcha ID="RadCaptcha_E" runat="server" ErrorMessage="Please enter the code shown correctly."
        CaptchaTextBoxLabel="ENTER CODE" EnableRefreshImage="true" CaptchaLinkButtonText="NEW IMAGE">
        <CaptchaImage CharSet="ABCDEABCDEABCDEABCDEABCDEABCDE" TextChars="CustomCharSet" />
    </telerik:RadCaptcha>
  • Yes the same code will appear on the CaptchaImage, but if the page is submitted the Captcha will be invalid. I tested a sample project and captured a video showing this behavior: http://www.screencast.com/users/metalmkd/folders/Jing/media/bef79c6f-d5f5-47e8-bb2b-83541ef3d3dc

Sincerely yours,
Pero
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kamil Zmeskal
Top achievements
Rank 1
answered on 19 May 2010, 04:02 PM
Hi Pero,

issue with CaptchaImage is solved. Thank you.

But issue with "back button" is still remaing. I has discovered then problem occurs when I make a Server.Transfer into another page. Please add into click method on Button1 Server.Transfer("Test.aspx").

Content on my page:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestWeb2.Default" EnableViewState="True" %> 
 
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %> 
 
<!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 runat="server">  
    <title></title>  
</head> 
<body> 
    <form id="form1" runat="server">  
    <asp:ScriptManager ID="ScriptManager1" runat="server">  
    </asp:ScriptManager> 
    <div> 
    <telerik:RadCaptcha ID="RadCaptcha1" runat="server" ErrorMessage="Bad code" RegisterWithScriptManager="True"   
    EnableRefreshImage="True" CaptchaLinkButtonText="New image" CaptchaTextBoxLabel="Insert code">  
    </telerik:RadCaptcha> 
      
    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" /> 
 
    </div> 
    </form> 
</body> 

using System;  
using System.Web;  
using System.Web.UI;  
using System.Web.UI.WebControls;  
 
namespace TestWeb2  
{  
    public partial class Default : System.Web.UI.Page  
    {  
        protected void Page_Load(object sender, EventArgs e)  
        {  
        }  
 
        protected void Button1_Click(object sender, EventArgs e)  
        {  
            Server.Transfer("Test.aspx");  
        }  
    }  

When I remove Server.Transfer then Captcha works OK and invoked "Bad code". But when I enable transfer to another page and return back, then Captcha doesn't invoke "Bad code".

Kamil
0
Pero
Telerik team
answered on 24 May 2010, 12:12 PM
Hi Kamil,

I am not sure that I clearly understand the problem. When transferring to another page, the Captcha performs validation, but because the user is transferred to another page s/he will never see the Error Message. When returning back, RadCaptcha generates a new code, and the old code entered by the user does not appear in the textbox. If you want to validate whether the correct code was entered, and then Transfer to another page, you should use the RadCaptcha.IsValid property.

In case the problem persists, please explain in more detail the erroneous behavior, and how do you expect the captcha to behave.

Best wishes,
Pero
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kamil Zmeskal
Top achievements
Rank 1
answered on 24 May 2010, 01:24 PM
Hi Pero,

I have already tried RadCaptcha.IsValid property but is true:

protected void Button1_Click(object sender, EventArgs e)  
{  
   if(RadCaptcha1.IsValid)  
   {  
      Server.Transfer("Test.aspx");  
   }  

Explicit validation don't works too.

protected void Button1_Click(object sender, EventArgs e)  
{  
   RadCaptcha1.Validate();  
 
   if(RadCaptcha1.IsValid)  
   {  
      Server.Transfer("Test.aspx");  
   }  
}  
 

Server.Transfer is executed ....

Kamil
0
Pero
Telerik team
answered on 27 May 2010, 09:08 AM
Hi Kamil,

Please, disregard my last post. I was wrong when saying that the Captcha will generate a new code when the user presses the browser's back button. Actually, what happens is the browser never requests the page from the server, but it loads the last state of the saved in the browser cache. When using Server.Transfer, the page containing the Captcha control will be cached with the current code, and a new Captcha code will never be generated. So, when you go back, and press the button to validate the code, the input will be validated as correct.
This is not the case when the page is not transferred. In a standard postback, a new code is generated, and the page with this new code is cached. When you go back and validate the code, an error message will be shown because the cached code is different then the one entered.

All this being said, means that this is expected behavior and we can't do anything to change the browser behavior.

All the best,
Pero
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kamil Zmeskal
Top achievements
Rank 1
answered on 27 May 2010, 10:55 AM
Hi Pero,

my point of view is that this captcha implementation isn't probably good :-(. I think that right behavior is not do allow to use one captcha code more than once (don't allow to use one code in twice (following) requests. This is basic rule and resolve this situation.

Kamil
0
Pero
Telerik team
answered on 01 Jun 2010, 03:35 PM
Hello Kamil,

As I said in my previous post, when you press the Back button of the browser, the page is not requested from the server, but it is loaded from the browser Cache. This means that all the controls on the page will be loaded with their last state persisted in the browser Cache (the Captcha will have the same code, and the TextBox will have the same Text). So, even if you change a property of the Captcha or any other control, before the page is transferred, the new value will not be persisted when you go back to the previous page. For example, if you reset the RadCaptcha.CaptchaImage.TextChars property to the same value (i.e. RadCaptcha1.CaptchaImage.TextChars = RadCaptcha1.CaptchaImage.TextChars;), a new text code will be generated. However, if you go back and submit the page, the Captcha again will be valid, which implies the new code was not persisted.

This is not a problem with our control, but a design limitation of the ASP.NET framework and we can't do much to avoid this behavior.

As a workaround you can handle the load client-side event of Sys.Application, and initiate an Ajax request to update the CaptchaImage. Please note that the refresh of the image should be enabled. Here is a sample code that implements this approach:
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Scripts>
            <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" />
        </Scripts>
    </asp:ScriptManager>
    <telerik:RadScriptBlock runat="server">
 
        <script type="text/javascript">
            Sys.Application.add_load(OnLoad);
            function OnLoad()
            {
                __doPostBack('RadCaptcha1$CaptchaLinkButton', '');
                Sys.Application.remove_load(OnLoad);
            }
        </script>
 
    </telerik:RadScriptBlock>
    <div>
        <telerik:RadCaptcha ID="RadCaptcha1" runat="server" ErrorMessage="Bad code" RegisterWithScriptManager="True"
            EnableRefreshImage="True" CaptchaLinkButtonText="New image" CaptchaTextBoxLabel="Insert code"
            ImageStorageLocation="Session">
        </telerik:RadCaptcha>
        <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
    </div>
    </form>
</body>
</html>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
public partial class Captcha_Default_Captcha : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Page.Title = "tt";
    }
 
    protected void Button1_Click(object sender, EventArgs e)
    {
        if (RadCaptcha1.IsValid)
        {
            RadCaptcha1.CaptchaImage.TextChars = RadCaptcha1.CaptchaImage.TextChars;
            ((TextBox)RadCaptcha1.FindControl("CaptchaTextBox")).Text = string.Empty;
            Server.Transfer("Test.aspx");
        }
    }
}


Kind regards,
Pero
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kamil Zmeskal
Top achievements
Rank 1
answered on 02 Jun 2010, 01:00 PM
Hi Pero ,

I think that using javascript on client side is not good solution :-(. Primary CAPTCHA function is protection from robots. Robots very easy bypass this solution.
I think that good solution is remove CAPTCHA code from cache after code is first used. There is server side validation. If client return back and try a new validation using previous code and code is not found in cache then captcha validation fail.
What is wrong in my idea? For me is it a basic CAPTCHA principe.

Kamil
0
Pero
Telerik team
answered on 04 Jun 2010, 03:31 PM
Hello Kamil,

When the new CaptchaImage is added to the Cache  (or the Session) the previous one is removed. So, the Cache (Session) contains the new image, but the browser will not made a request to the server for the new image, when the back the button is pressed, but will load the page with the state saved in the browser cache.
Here is an example showing that even if the object is removed from the Cache, the browser will behave as it is still present:

aspx
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <asp:Button ID="Button1" runat="server" ValidationGroup="VG" Text="Server transfer"
            OnClick="Button1_Click" />
    </div>
    </form>
</body>
</html>

cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Caching;
 
public partial class Default_Captcha : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Context.Cache.Add("Key", "Value", null, DateTime.Now.AddSeconds(Convert.ToDouble(5 * 60)), TimeSpan.Zero, CacheItemPriority.NotRemovable, null);
        }
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        if (Context.Cache["Key"] == "Value")
        {
            Context.Cache.Remove("Key");
            Page.Title = DateTime.Now.ToString();
            Server.Transfer("~/Default.aspx");
        }
    }
}
  

All the best,
Pero
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kamil Zmeskal
Top achievements
Rank 1
answered on 04 Jun 2010, 05:51 PM

I'm sorry but I still don't understand this implementation :-(

My point on view:>When the new CaptchaImage is added to the Cache 
>(or the Session) the previous one is removed

This is wrong. Old CaptchaImage must be removed from Cache when is successful validated. No when a new CaptchaImage has generated. It's late.

1. Server generate CAPTCHA image 123456 (and save code 123456 into a server cache) and the image is displayed on the client page
2. Client see image with code 123456 and enter this code into a CAPTCHA TextBox control a make a click on "OK" button
3. Request is sended to server and server get code 123456 from server cache and validate code and remove this code from server cache
4. Client go back with "Back" button and display page from browser cache with code 123456
5. Client see image with old code 123456 and make a click on "OK" button
6. Request id sended to server and server don't found code 123456 in server cache because in previous validation remove this code from server cache

Where I have a mistake in this steps?

Kamil

0
Pero
Telerik team
answered on 09 Jun 2010, 09:46 AM
Hi Kamil,

RadCaptcha follows the exact set of steps you described in your post:

  1. The server generates a CAPTCHA image 123456 (and saves the code together with the image into the server cache or session) and the image is displayed on the client page.
  2. The client enters the correct code and clicks a button to verify the code.
  3. The code is validated on the server, then it (together with the image) is removed from the server cache/session and a new one is added to the cache.
Since you perform a Server.Transfer on a button.Click the request will not be finished on the current page, but will be transferred to a new page. This causes the previous state of the page to be cached (i.e. the current request was not finished), and that's why when you go back and validate the code, the old code will be still valid. This leads to the conclusion that the server.Transfer method should be postponed to a later stage, when the state related processing has been finished. So, I moved the Server.Transfer method to the Page.Render, and it seems to be working now. You could however test this solution more extensively to see if it works in all cases.

The sample code is attached to the thread.

Best wishes,
Pero
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kamil Zmeskal
Top achievements
Rank 1
answered on 09 Jun 2010, 08:51 PM
Hi Pero,
I have tried to use Server.TransferRequest instead of Server.Transfer and it's fine. CAPTCHA code is not validated twice. This is probably little better solution for me than move Server.Transfer into Page.Render. Do you see any problem to use this method?
Kamil
0
Accepted
Pero
Telerik team
answered on 10 Jun 2010, 04:37 PM
Hi Kamil,

I am glad that the problem has been resolved.

I am not really familiar with this method and I can't say whether there are any problems with using it. In some articles on the internet I have read that the only limitation of the Server.TransferRequest method, is that it works only on IIS7. If the web site is hosted on an earlier version of IIS it will not work.

Here is some more information regarding the method:


All the best,
Pero
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kamil Zmeskal
Top achievements
Rank 1
answered on 10 Jun 2010, 08:01 PM
Thank you.
0
Enigma
Top achievements
Rank 1
answered on 08 Nov 2010, 02:36 AM
Hi Pero,

I am having a problem with RadCaptcha.  I have it on a Contact page.  When the user fills out the information, the page posts back and emails the information to the admin.  I then hide the div that has the form and display another div to show thank you message.  We are on the same page so no Transfer. If the user clicks on Back button in the browser then he/she can postback again using the same code.  No problem.  I do check for IsValid property before sending out the email and the ISValid always returns true

if (Page.IsValid && RadCaptcha1.IsValid)
            {
                try
                {
                    StringBuilder str = new StringBuilder();
                    str.AppendLine("Name: " + txtName.Text);
                    str.AppendLine("Company: " + txtCompany.Text);
                    str.AppendLine("Email: " + txtEmail.Text);
                    str.AppendLine("Phone: " + txtPhone.Text);
                    str.AppendLine("Message: " + txtMessage.Text);

                    MailHelper.Instance.SendSystemOwnerEmail("[Call The Time] Contact form filled out.", str.ToString());

                    CTTUtility.Instance.SendDataToSalesForce(txtName.Text,
                        string.Empty, txtCompany.Text, string.Empty,
                        string.Empty,
                        txtPhone.Text,
                        txtEmail.Text,
                        txtMessage.Text,
                        "[Call The Time] Contact form filled.");

                    this.txtCompany.Text = string.Empty;
                    this.txtEmail.Text = string.Empty;
                    this.txtMessage.Text = string.Empty;
                    this.txtPhone.Text = string.Empty;
                    this.txtName.Text = string.Empty;

                    RadCaptcha1.CaptchaImage.RenderImage();

                    divContact.Visible = false;
                    divThankYou.Visible = true;
                }
if (Page.IsValid && RadCaptcha1.IsValid)
            {
                try
                {
                    StringBuilder str = new StringBuilder();
                    str.AppendLine("Name: " + txtName.Text);
                    str.AppendLine("Company: " + txtCompany.Text);
                    str.AppendLine("Email: " + txtEmail.Text);
                    str.AppendLine("Phone: " + txtPhone.Text);
                    str.AppendLine("Message: " + txtMessage.Text);

                    MailHelper.Instance.SendSystemOwnerEmail("[Call The Time] Contact form filled out.", str.ToString());

                    CTTUtility.Instance.SendDataToSalesForce(txtName.Text,
                        string.Empty, txtCompany.Text, string.Empty,
                        string.Empty,
                        txtPhone.Text,
                        txtEmail.Text,
                        txtMessage.Text,
                        "[Call The Time] Contact form filled.");

                    this.txtCompany.Text = string.Empty;
                    this.txtEmail.Text = string.Empty;
                    this.txtMessage.Text = string.Empty;
                    this.txtPhone.Text = string.Empty;
                    this.txtName.Text = string.Empty;

                    RadCaptcha1.CaptchaImage.RenderImage();

                    divContact.Visible = false;
                    divThankYou.Visible = true;
                }
if (Page.IsValid && RadCaptcha1.IsValid)
            {
                try
                {                                       MailHelper.Instance.SendSystemOwnerEmail("Contact form filled out.", txtName.Text);                  
 
                    this.txtName.Text = string.Empty;
                    // With the code below or without it.  The CAPTCHA image doesnt change and the user can click on Back button and use the same code to postback.
                    RadCaptcha1.CaptchaImage.RenderImage();
 
                    divContact.Visible = false;
                    divThankYou.Visible = true;
                }
0
Pero
Telerik team
answered on 10 Nov 2010, 05:01 PM
Hi Enigma,

Please, call the RadCaptcha.Validate and Page.Validate methods before checking for the RadCaptcha's IsValid property, to be sure the validation actually has occurred.

Basically your code should look like the following:
RadCaptcha1.Validate();
Page.Validate();
 
if (Page.IsValid && RadCaptcha1.IsValid)
            {
                try
                {                                       MailHelper.Instance.SendSystemOwnerEmail("Contact form filled out.", txtName.Text);                 
  
                    this.txtName.Text = string.Empty;
                    // With the code below or without it.  The CAPTCHA image doesnt change and the user can click on Back button and use the same code to postback.
                    RadCaptcha1.CaptchaImage.RenderImage();
  
                    divContact.Visible = false;
                    divThankYou.Visible = true;
                }


Sincerely yours,
Pero
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
Captcha
Asked by
Kamil Zmeskal
Top achievements
Rank 1
Answers by
Pero
Telerik team
Kamil Zmeskal
Top achievements
Rank 1
Enigma
Top achievements
Rank 1
Share this question
or