5

I have a new table that hold old passwords, I need to check if there is a match.

If there is a match I need the ChangePassword contol to NOT change the password. I need to tell the user that this password was used and pic a new one.

I can't seem to be able to interrupt the control from changing the password. Maybe I am using the wrong event.

Here is a piece of my code, or how I wish it would work. I appreciate all your help.

protected void ChangePassword1_ChangedPassword(object sender, EventArgs e)
    {
        MembershipUser user = Membership.GetUser();
        string usrName = "";
        if (user != null)
        {
            string connStr = ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString;
            SqlConnection mySqlConnection = new SqlConnection(connStr);
            SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
            mySqlCommand.CommandText = "Select UserName from OldPasswords where UserName = 'test'";
            mySqlConnection.Open();
            SqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader(CommandBehavior.Default);
            while (mySqlDataReader.Read())
            {
                usrName = mySqlDataReader["UserName"].ToString();
                if (usrName == user.ToString())
                {

                    Label1.Text = "Match";
                }
                else
                {
                    Label1.Text = "NO Match!";
                }
            }
Steve
  • 1,028
  • 7
  • 25
  • 42
  • 1
    I'm not sure what you're trying to do here. You talk about wanting to verify old passwords, but your SQL statement retrieves usernames and never checks the passwords. How are you verifying the password itself? – cortijon Apr 27 '10 at 13:09
  • Yes, you are correct, that piece of code is on a different page, I was just real quick putting together a test page, sorry about the confusion. I just had trouble interrupting the process itself. Thank you for your input. – Steve Apr 28 '10 at 02:29
  • @Sky - Yes, I am actually all done, I am now cleaning up the code, testing some more. I will post it all soon. Thank you again for all your help! – Steve May 02 '10 at 14:36
  • All the thanks I need are upvotes and checkmarks! glad to help. – Sky Sanders May 02 '10 at 15:06

1 Answers1

6

You are overriding the wrong method, Steve. You want to override the cancellable ChangingPassword.

Try this:

protected void ChangePassword1_ChangingPassword(object sender, LoginCancelEventArgs e)
{
    // do your lookup here, 
    bool passwordHasBeenPreviouslyUsed = true;

    if (passwordHasBeenPreviouslyUsed)
    {
        e.Cancel = true;
        // notify of error
        return;
    }

}

And, as per previous Q/A sessions, You should NEVER EVER EVER store a user's password1. Go to the membership table and get the salt and use that to hash the incoming password to compare to the already salt-hashed values you have stored in your lookup table.

Good luck.

(1) - how tenable would your position be when the CEO finds out that his password has been stored in an exploitable format? There is a level of trust given to the black mages that are us and that trust carries it's own risks. Be aware of them. ;-)

EDIT:

A working example:

ChangePassword.aspx

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics"%>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void ChangePassword1_ChangingPassword(object sender, LoginCancelEventArgs e)
    {
        // works for me!
        Debugger.Break();
    }
</script>

<!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">
    <div>
        <asp:ChangePassword ID="ChangePassword1" runat="server" OnChangingPassword="ChangePassword1_ChangingPassword">
        </asp:ChangePassword>
    </div>
    </form>
</body>
</html>

Update: You may also be interested in simply defining a handler in a higher scope that will watch all password activity:

consider this

public void SetupPasswordActionHook()
{

    //Occurs when a user is created, a password is changed, or a password is reset.
    Membership.ValidatingPassword += Membership_ValidatingPassword;
}

void Membership_ValidatingPassword(object sender, ValidatePasswordEventArgs e)
{

    // Gets a value that indicates whether the System.Web.Security.MembershipProvider.ValidatingPassword event is being raised during a 
    // call to the System.Web.Security.MembershipProvider.CreateUser() method.

    // true if the System.Web.Security.MembershipProvider.ValidatingPassword event is being raised during a call to the 
    // System.Web.Security.MembershipProvider.CreateUser() method; otherwise, false.
    bool isNewUser = e.IsNewUser;

    // Gets the password for the current create-user, change-password, or reset-password action.

    // The password for the current create-user, change-password, or reset-password action.
    string password = e.Password;

    // Gets the name of the membership user for the current create-user, change-password, or reset-password action.

    // The name of the membership user for the current create-user, change-password, or reset-password action.
    string username = e.UserName;

    // Gets or sets a value that indicates whether the current create-user, change-password, or reset-password action will be canceled.

    // true if the current create-user, change-password, or reset-password action will be canceled; otherwise, false. The default is false.
    e.Cancel = true;

    // Gets or sets an exception that describes the reason for the password-validation failure.

    // An System.Exception that describes the reason for the password-validation failure.
    e.FailureInformation = new Exception("This is why I failed your password");

}
Sky Sanders
  • 36,396
  • 8
  • 69
  • 90
  • Thank you so much for your code sample, I will try that out. I am of course NOT saving anything in clear format, the password are hashhed in both tables and I store the salt with it. I has the password that the user enters and then compare it with the one I have in my "OldPassword" table. Again, thank your for your help. – Steve Apr 28 '10 at 02:32
  • @Steve - (putting on psychic hat) hmm.... I sense that you may not have specified on the control that the ChangingPassword eventHandler is ChangePassword1_ChangingPassword. (taking off psychic hat) How did I do? ;-) – Sky Sanders Apr 29 '10 at 11:55
  • @Steve - I was cleaning up some of my old code and found another example of how to handle password activity in a higher scope that may be of interest. – Sky Sanders Apr 30 '10 at 04:58
  • @SkySanders, great answer, but I liked the term `Black Mage` more. – AaA Jan 30 '13 at 03:06