Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

override Login Authentication Function

Posted on 2007-08-19
25
Medium Priority
?
2,476 Views
Last Modified: 2012-05-05
Hi,

I am trying to add a CAPTCHA control to my website as in:
http://aspnet.4guysfromrolla.com/articles/060706-1.aspx

I've succeeded adding the control and everything is showing fine, but I don't know how to override the Authentication Function to check the if the text entered is valid. I am using c# btw
0
Comment
Question by:Dirar Abu Kteish
  • 15
  • 10
25 Comments
 
LVL 18

Expert Comment

by:DropZone
ID: 19725366
Hi dxz2!

I'm not sure I understand your question, and at the risk of making a stupid assumption, I will explain how to extend the Login control.  Below is a sample based on the VB.NET code of the page you referenced.  Please note that my C# is rusty as I don't use it much -- I program mostly in Delphi.NET.

    // Descend from the Login control
    public class MyLoginControl : Login {

       protected override void Authenticate(System.Object sender, System.Web.UI.WebControls.AuthenticateEventArgs e) {
            // We need to determine if the user is authenticated and set e.Authenticated accordingly
            // Get the values entered by the user
            string loginUsername = MyLogin.UserName;
            string loginPassword = MyLogin.Password;
            string loginEmail;

            // Defaultl to false
            e.Authenticated = False;

            // To get a custom Web control, must use FindControl
            TextBox emailctrl = this.FindControl("Email") As TextBox;
            if (emailctrl != null) {
                loginEmail = emailctrl.Text;
            }

            WebControlCaptcha.CaptchaControl loginCAPTCHA = this.FindControl("CAPTCHA") as WebControlCaptcha.CaptchaControl;
            if (loginCAPTCHA != null) {
                // First, check if CAPTCHA matches up
                if (! loginCAPTCHA.UserValidated) {
                    // CAPTCHA invalid
                    MyLogin.FailureTex = "The code you entered did not match up with the image provided.";
                } else {
                    // Next, determine if the user's username/password are valid
                    if (Membership.ValidateUser(loginUsername, LoginPassword) {
                        // See if email is valid
                        MembershipUser userInfo = Membership.GetUser(loginUsername);
                        if (string.Compare(userInfo.Email, loginEmail, true) <> 0) {
                           // Email doesn't match up
                           MyLogin.FailureText = "The email address you provided is not the email address on file.";
                        } else {
                            // Only set e.Authentication to true if ALL checks pass
                            e.Authenticated = true;
                        }
                    } else {
                        MyLogin.FailureText = "Your username and/or password are invalid.";
                    }
                }
            }
       }
    }    

Here is some information on creating custom controls by extending built-in ones:
http://samples.gotdotnet.com/quickstart/aspplus/

     -dZ.
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19725385
Oops! There's an error in my code: replace all instances of "MyLogin" with "this".  The corrected code should be:

    // Descend from the Login control
    public class MyLoginControl : Login {

       protected override void Authenticate(System.Object sender, System.Web.UI.WebControls.AuthenticateEventArgs e) {
            // We need to determine if the user is authenticated and set e.Authenticated accordingly
            // Get the values entered by the user
            string loginUsername = MyLogin.UserName;
            string loginPassword = MyLogin.Password;
            string loginEmail;

            // Defaultl to false
            e.Authenticated = False;

            // To get a custom Web control, must use FindControl
            TextBox emailctrl = this.FindControl("Email") As TextBox;
            if (emailctrl != null) {
                loginEmail = emailctrl.Text;
            }

            WebControlCaptcha.CaptchaControl loginCAPTCHA = this.FindControl("CAPTCHA") as WebControlCaptcha.CaptchaControl;
            if (loginCAPTCHA != null) {
                // First, check if CAPTCHA matches up
                if (! loginCAPTCHA.UserValidated) {
                    // CAPTCHA invalid
                    this.FailureTex = "The code you entered did not match up with the image provided.";
                } else {
                    // Next, determine if the user's username/password are valid
                    if (Membership.ValidateUser(loginUsername, LoginPassword) {
                        // See if email is valid
                        MembershipUser userInfo = Membership.GetUser(loginUsername);
                        if (string.Compare(userInfo.Email, loginEmail, true) <> 0) {
                           // Email doesn't match up
                           this.FailureText = "The email address you provided is not the email address on file.";
                        } else {
                            // Only set e.Authentication to true if ALL checks pass
                            e.Authenticated = true;
                        }
                    } else {
                        this.FailureText = "Your username and/or password are invalid.";
                    }
                }
            }
       }
    }    


I also forgot to mention that once you extend your login control, you use that instead of the <asp:Login> control on your page.  To do this, first you need to register the control on your page like this:

<%@ Register TagPrefix="MyCustomControls" Namespace="MyNamespace" Assembly="MyControlsAssembly" %>

The TagPrefix represents the prefix you will use to differentiate your controls.  This replaces the <ASP: prefix on the built-in controls.  For example:
     <MyCustomControls:MyLoginControl>

The Namespace and Assembly attributes represent, respectively, the namespace and the assembly to which your custom control belongs.

     -dZ.
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19725438
Hello -dZ, thanks for replying.
I'll give it a try tomorrow and get back
0
Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19728494
I already have a login control, from my last question. I don't want to override the method Authenticate in that control but I want to override it in the code of the login page, is this possible?

-dirar
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19728512
The code is still full of errors, after correction:

protected override void Authenticate(System.Object sender, System.Web.UI.WebControls.AuthenticateEventArgs e) {
            // We need to determine if the user is authenticated and set e.Authenticated accordingly
            // Get the values entered by the user
            string loginUsername = MyLogin.UserName;
            string loginPassword = MyLogin.Password;
            string loginEmail;

            // Defaultl to false
            e.Authenticated = False;

            // To get a custom Web control, must use FindControl
            TextBox emailctrl = this.FindControl("Email");
            if (emailctrl != null) {
                loginEmail = emailctrl.Text;
            }

            WebControlCaptcha.CaptchaControl loginCAPTCHA = this.FindControl("CAPTCHA");
            if (loginCAPTCHA != null) {
                // First, check if CAPTCHA matches up
                if (! loginCAPTCHA.UserValidated) {
                    // CAPTCHA invalid
                    this.FailureTex = "The code you entered did not match up with the image provided.";
                } else {
                    // Next, determine if the user's username/password are valid
                    if (Membership.ValidateUser(loginUsername, LoginPassword)){
                        // See if email is valid
                        MembershipUser userInfo = Membership.GetUser(loginUsername);
                        if (string.Compare(userInfo.Email, loginEmail, true) != 0) {
                           // Email doesn't match up
                           this.FailureText = "The email address you provided is not the email address on file.";
                        } else {
                            // Only set e.Authentication to true if ALL checks pass
                            e.Authenticated = true;
                        }
                    } else {
                        this.FailureText = "Your username and/or password are invalid.";
                    }
                }
            }
       }
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19728530
Also when adding to the control that I already have I get this error:

'CssWebControls.CssLogin.Authenticate(object, System.Web.UI.WebControls.AuthenticateEventArgs)': cannot override because 'System.Web.UI.WebControls.Login.Authenticate' is not a function


0
 
LVL 18

Expert Comment

by:DropZone
ID: 19729234
>> I already have a login control, from my last question. I don't want to override the method Authenticate in that control but I want to override it in the code of the login page, is this possible?

I don't understand what you mean.  The Authenticate method is a protected method of the Login control.  In order to override it, you must extend the control by creating a descendant.  You could add your code to the already overriden code, or you could extend it once more.

I'm sorry for the errors in the code, but I do not use C# (I use Delphi and C), and I tried my best to convert the VB code in the example, plus I don't have a compiler to test it.

Can you post the code for your Authenticate method?  That error means that the Authenticate method that you defined could not be found in the base class.  You must make sure that the function declaration matches the original one.

      -dZ.
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19729247
That's what I get for translating from stupid VB.  The method is an event delegate called OnAuthenticate and it only has one argument.  The signature of the method is:

override protected void OnAuthenticate(AuthenticateEventArgs e)

That should work.
http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.login.onauthenticate.aspx

    I'm sorry for that.
      -dZ.
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19729263
And one last thing. Since it is an event delegate, it will trigger and event.  This means that you should be able to have an event handler on your page and use *that* instead of having to override the control all the time, just like you wanted.

But in order for the even to be triggered, you need to make sure that your overriden method calls the base method at some point, which is the one that fires the event.  Otherwise, the event won't get fired.

My apologies for this.  I am currently stuck on .NET 1.1 in Delphi, so my experience with .NET 2.0 controls is limited to what I have read.  I hope this helps anyway.

    -dZ.
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19729321
Hello -dZ,

I think your help is very good, after all I just need to be redirected.

The function worked inside the control I am using, the one from my last question to you: http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_22756255.html

What I want, if it's possible to override the OnAuthenticate function from the code behind page and not from the overridden login control. The login control I created is compiled into DLLs and added to my page as reference. I don't want to add the reference to the CAPTCHA control in both places(The login control and my web site).
Another way to say it, is how can I override the OnAuthenticate function from code behind page? i know the function is protected but how can I extend it one more time to override it

Hope you understand what I mean.... If not please let me know I will try to explain what I want in different way

I appreciate your help, thanks

-dirar



0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19729375
the reason I want to override the OnAuthenticate function in he login page is that I want to load some variables that depends on the user choice, such as interface language and some other information. I think it would be better if everything is in one place

-dirar
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19730209
>> What I want, if it's possible to override the OnAuthenticate function from the code behind page and not from the overridden login control.

As I mentioned in my last message, since the method is an event, you do "override" the function from the code-behind, but you "handle" the event there.  Just add an event handler for that event in your page.  I'm not sure how this is done in VisualStudio, but I think you just add an attribute such like OnAuthenticate="AuthenticateHandler" to the Login control on the page and then implement Page_AuthenticateHandler event handler.  You can also register the event handler from code.  Let me know if you need help doing this and I'll research it.

>> the reason I want to override the OnAuthenticate function in he login page is that I want to load some variables that depends on the user choice, such as interface language and some other information. I think it would be better if everything is in one place

I agree.  I had been confused by the VB code on the example page, assuming that Authenticate() was the method and that it needed to be overriden.  However, the example clearly shows that the Authenticate() method they implemented is actually a custom event handler wired to the OnAuthenticate event.  I missed that.  Since I didn't have experience with the Login control, I didn't know about that event.

Handling this event will allow you to add custom authentication code to any page while using the same control.

     -dZ.
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19731729
Well I tried before using the OnAuthenticate also Onloginin evets before but I got some error that I don't remmber now.
I am home now and the code I have at work, I'll be back tomorrow with the error

Thanks

-dirar
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19735830
Hello dZ,
I am back with the error:
'Aspx_login.MyFunction(System.Web.UI.WebControls.AuthenticateEventArgs)' is inaccessible due to its protection level

Called like this:
<CssWebControls:CssLogin id="Login" runat="server" DestinationPageUrl="Main.aspx" OnAuthenticate="MyFunction">

the function:

void MyFunction(AuthenticateEventArgs e) {
        Login.FailureText = "Cocojambo";
 }


0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19735855
I tried to change the function like this:

protected void MyFunction(AuthenticateEventArgs e)

then i got:

No overload for 'MyFunction' matches delegate 'System.Web.UI.WebControls.AuthenticateEventHandler'      

0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19735981
I've found this page http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.authenticateeventargs.aspx  did exactly the same but still getting the same error.

Then I opened a new page and tried it it worked, then I went back to my old age and removed the captcha and it worked as in in the link.  I removed the textbox from the Captcha control and it worked. I still don't know what is wrong with it

0
 
LVL 18

Accepted Solution

by:
DropZone earned 2000 total points
ID: 19736501
Hum... wierd.

Can you try this way?
protected void MyFunction(System.Object sender, AuthenticateEventArgs e)

This is ridiculous:  I find conflicting references, some using 2 parameters and some using only 1.  However, in my experience, when you call an event, it includes the sender as part of the call.  Besides, the last error you got means that it cannot find a MyFunction() declaration that matches the signature defined by the event handler.  But since I'm not very familiar with C# and VB.Net, your mileage may vary.

     -dZ.
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19736533
The event is now working because I removed the CAPTCHA from the code. I am really going crazy dealing with strange behavior in .NET. When the captcha control is added it seems that it ignores the overridden event function, when I remove it it works great.

But I will give u the points for this question and I will try using another Captcha hopefully it will work.

Now I am going crazy with Application getting empty somehow.

I am sure I'll be back with something else very soon :(

-dirar
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19736555
Post the code with the CAPTCHA, perhaps its not the CAPTCHA control after all but something strange in the code.

What do you mean "Application getting empty", the Application State collection?

    -dZ.
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19736589
This is my login control page:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Aspx_login"%>
<%@ Register TagPrefix="CssWebControls" Namespace="CssWebControls" Assembly="CssWebControls" %>
<%@ Register TagPrefix="cc1" Namespace="WebControlCaptcha" Assembly="WebControlCaptcha" %>

<!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 id="Head1" runat="server">
        <title>New Sound Content Manager</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <CssWebControls:CssLogin id="Login1" runat="server" OnAuthenticate="OnAuthenticate">
                <LayoutTemplate>
                    <div id="login-main-container">
                        <div id="login-container">
                            <div id="login-area">
                                <div id="form-area">
                                    <p class="failure-text">
                                        <asp:Literal id="FailureText" runat="server" EnableViewState="False"></asp:Literal>
                                    </p>
                                    <p>
                                        <asp:label id="UserNameLabel" runat="server" AssociatedControlID="UserName" CssClass="labels">User Name:</asp:label>
                                        &nbsp;<asp:TextBox id="UserName" runat="server" CssClass="text"></asp:TextBox><asp:RequiredFieldValidator id="UserNameRequired" runat="server" ValidationGroup="Login1" ControlToValidate="UserName" ToolTip="User Name is required." ErrorMessage="User Name is required.">*</asp:RequiredFieldValidator>
                                    </p>
                                    <p>
                                        <asp:label id="PasswordLabel" runat="server" AssociatedControlID="Password" CssClass="labels">Password:</asp:label>
                                        &nbsp;<asp:TextBox id="Password" runat="server" TextMode="Password" CssClass="text"></asp:TextBox><asp:RequiredFieldValidator id="PasswordRequired" runat="server" ValidationGroup="Login1" ControlToValidate="Password" ToolTip="Password is required." ErrorMessage="Password is required.">*</asp:RequiredFieldValidator>
                                    </p>
                                    <p>
                                        <asp:CheckBox id="RememberMe" runat="server" Text="Remember me next time." CssClass="checkbox"></asp:CheckBox>
                                    </p>
                                    <cc1:CaptchaControl id="CAPTCHA" runat="server" EnableViewState="False" LayoutStyle="horizontal" TabIndex="4" CaptchaImgClass="captcha-image" ></cc1:CaptchaControl>
                                    <p>
                                        <asp:Button id="LoginButton" runat="server" ValidationGroup="Login1" Text="Log In" CommandName="Login" CssClass=" submit"></asp:Button>
                                    </p>
                                </div>
                            </div>
                        </div>
                    </div>
                </LayoutTemplate>
            </CssWebControls:CssLogin>      
        </form>
    </body>
</html>


Code behind page:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using DDBLibrary;

public partial class Aspx_login : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
       
    }    

    protected void OnAuthenticate(object sender, AuthenticateEventArgs e)
    {
               Login.FailureText = "Cocojambo";        
    }

}


When I remove the Captcha the code is running and everything is fine, but when added the code just run and my OnAuthenticate function seems to be ignored.

I got the Captcha from:

http://www.codeproject.com/aspnet/CaptchaControl.asp

-dirar

   
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19736654
About the application. I am setting an Application from the OnAuthenticate function with values from xml file. The first time it's loaded but when I refresh the page the application gets empty..
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19736671
dxz2,
     I haven't analysed the code for the CAPTCHA control thoroughly, but from the explanation on that article it seems to do some very strange things to make itself work.  I wouldn't be surprised if it for some reason "took over" events on the page by hijacking the processing life-cycle of the page somehow.  The author claims that his controls is "A good net citizen", but it stands to reason that it may have been designed to work on its own (without Login controls).

     Also, it exposes an event called UserValidationEvent(), which makes me think it overshadows your other event.  Try implementing that event and see if it triggers.  Also, put a breakpoint in it and check the call stack (and post it here if you can).  I'd be interested in know when in the life-cycle it fires up.

      In any case, if you are not keen to play with the CAPTCHA control source to modify it for your purposes, then I suggest you find a different one.

     -dZ.
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19736739
Yes I think you are right about the event being overshadowed from the CAPTCHA control. But I've been searching for the function that does that and never find it. There is the _userValidated and it's a boolean variable that tells whether the user passed the validation or not.  I tried to comment the code where it writes the text input field to the page and it worked. Which is this part:

.Write("<input name=""" & UniqueID & """ type=""text"" style=""width:")
            .Write(_captcha.TextLength.ToString & "em;""")
            .Write(" class=""captcha-textbox"" maxlength=""")
            .Write(_captcha.TextLength.ToString & """")
            If AccessKey.Length > 0 Then
                .Write(" accesskey=""" & AccessKey & """")
            End If
            If Not Enabled Then
                .Write(" disabled=""disabled""")
            End If
            If TabIndex > 0 Then
                .Write(" tabindex=""" & TabIndex.ToString & """")
            End If
            .Write(" value="""" />")

I have no clue why this is happening, after all it's a normal text input. But  somehow it triggers the event when pressing enter and not when clicking on the login button.

-dirar
0
 
LVL 18

Expert Comment

by:DropZone
ID: 19736825
Check the following:

            If AccessKey.Length > 0 Then
                .Write(" accesskey=""" & AccessKey & """")
            End If

My guess is that by default its setting an AccessKey and its expecting the user to hit enter.  Your button then doesn't stand a chance since it is outside the domain of the CAPTCHA control (if indeed it takes over events on the page).

I'm sorry, but I don't think I'll have time to thoroughly analise the CAPTCHA code, though I wish I could.  However, if you can't find a substitute control that works, I suggest you play with the code and see what you can find.  You can always post some code here if you have questions or problems and I'll try to help as I can.  I'll continue monitoring this question until you are satisfied that it works.

I would gladly give you my personal e-mail address to continue this discussion, if there was a safe way to offer it without publicizing it to everyone. :)

    -dZ.
0
 
LVL 6

Author Comment

by:Dirar Abu Kteish
ID: 19737262
this is my spam email, send to me an email and I'll reply from my email. Same as my user name @yahoo.com

Thanks


0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today, the web development industry is booming, and many people consider it to be their vocation. The question you may be asking yourself is – how do I become a web developer?
Although a lot of people devote their energy toward marketing for specific industries, there are some basic principles that can be applied to any sector imaginable. We’ll look at four steps to take and examine how those steps were put into action fo…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).
Suggested Courses

783 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question