2

I am truly puzzled by this.

We were giving a spec to build an app that requires users to create their own accounts before using the app.

The spec says that user's email should be validated against the email s/he has on our database.

If that email already exists, inform the user and ask him/her to choose another.

Below is the code that does all that.

//Markup:

<tr>
   <td height="27" width="129"><font face="Tahoma" size="2">
   <label for="txtEmail">Your Email address:</label></font></td>
   <td height="27" width="244">
     <asp:TextBox ID="txtEmail" CssClass="Treb10Blue" Runat="server"  style="font-family: Trebuchet MS; font-size: 10pt; font-weight: bold; font-style: italic; color: #000080;"></asp:TextBox>
     <asp:RequiredFieldValidator ID="RequiredFieldValidator4" Runat="server" ErrorMessage="*" Display="Dynamic" ControlToValidate="txtEmail"></asp:RequiredFieldValidator>
     <asp:RegularExpressionValidator ID="RegularExpressionValidator1" ControlToValidate="txtEmail" ValidationExpression=".*@.*\..*" ErrorMessage="Email not in correct format" Display="Dynamic" Runat="server"></asp:RegularExpressionValidator>
   </td>
</tr>

//Then codebehind

Function Fixquotes(ByVal thesqlenemy As String) As String
    Fixquotes = Replace(thesqlenemy, "'", "''")
End Function

Sub btnRegister_Onclick(ByVal Src As Object, ByVal e As System.Web.UI.ImageClickEventArgs)
    If Page.IsValid Then
        Dim objConn As IDbConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("DBConnectionString").ConnectionString)
        Dim chkUsername As IDbCommand
        Dim addUser As IDbCommand
        Dim strSQL1 As String
        Dim strSQL2 As String
        Dim strUserCount As Integer

    'first, check if user already exists
        Try
            strSQL1 = "SELECT COUNT(*) FROM [tblLogin] WHERE [Email]='" & Fixquotes(txtEmail.Text) & "'"
            strSQL2 = "INSERT INTO [tblLogin] ([Fullname], [Email], [Username], [Password],[Rights],[ModifiedDate],Precinct,PositionId,ProcessedFlag)"
            strSQL2 = strSQL2 & " VALUES "
            strSQL2 = strSQL2 & "('" & Fixquotes(txtFullname.Text) & "', '" & Fixquotes(txtEmail.Text) & "', '" & Fixquotes(txtUsername.Text) & "', '" & Fixquotes(txtPassword.Text) & "',2,getdate(), '" & precinctList.SelectedValue & "'," & PosisitionList.SelectedValue & ",'No')"
            'Response.Write(strSQL2)
            'Response.End()
            objConn.Open()
            chkUsername = New SqlCommand(strSQL1, objConn)
            strUserCount = chkUsername.ExecuteScalar()
            If strUserCount = 0 Then
                addUser = New SqlCommand(strSQL2, objConn)
                addUser.ExecuteNonQuery()
                objConn.Close()
                'Display some feedback to the user to let them know it was sent
                lblMsg.ForeColor = System.Drawing.Color.Green
                lblMsg.Text = "Your account has been successfully created.<br><br>Please click the Close button below to close this window and log in with your newly created username and password."


                'Clear the form
                txtFullname.Text = ""
                txtEmail.Text = ""

            Else
                lblMsg.Text = "That email address already exists. Please choose another..."
                lblMsg.ForeColor = Drawing.Color.Red
            End If
        Catch

            objConn.Close()

        End Try
    End If
End Sub

So far, out of a total of 1,035 users who have signed up, nine (9) of them have been able to create duplicate accounts using SAME email address.

One of those users did it 5 times!

How is this possible and how do I prevent further occurences?

Thanks a lot in advance

4

3 回答 3

2

您可能会在非常快的时间内连续发生请求,并且在执行查询之间的时间内,该值不再是唯一的。将所有内容封装在事务中可以防止这种情况发生,并且就实践而言,您应该考虑将其放入存储过程中。

于 2013-10-02T19:25:07.253 回答
1

阻止重复条目的一种方法是通过对数据库表中的列施加UNIQUE约束来阻止重复数据进入数据库。[Email]

然后,至少,当重复INSERT尝试发生时会引发异常。

于 2013-10-02T19:14:19.497 回答
1

是的,这是可能的,但 5 次似乎很难做到。很可能,用户双击,导致代码运行两次。现在,因为在查询是否存在和创建它之间有一段时间,所以可以创建多个。

要解决此问题,有几种方法。

您可以查看在您的代码TransactionScope中实现事务

您可以在您的 SQL SQL 事务中实现事务

或者,我最喜欢的是,以事务性的方式编写 SQL 将两个 SQL 语句放入 1 个以“IF NOT EXISTS(SELECT TOP 1 1 FROM [tblLogin] WHERE [Email]='”和 Fixquotes(txtEmail.Text) 开头的字符串中) & "'" & YourInsertSqlHere

然后,当您使用 ExecuteNonQuery() 运行此 SQL 时,保留结果,如果为 0,则表示它没有插入,因为它已经存在。

但首先,通过在您执行任何其他操作之前禁用按钮来解决双击问题!

于 2013-10-02T19:24:45.840 回答