我正在开发一个需要注册页面的ASP.NET项目。以下代码验证用户名或电子邮件地址是否已存在,但如果一切正常,则不会将数据插入数据库。我做错了什么?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Configuration;
using System.Drawing;
namespace BootstrapRegisterLogin
{
public partial class SignUp : System.Web.UI.Page
{
bool flag = false;
protected void Page_Load(object sender, EventArgs e)
{
}
private String EncryptPassword(string pass)
{
pass = tbPass.Text;
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(pass);
string EncryptedPassword = Convert.ToBase64String(bytes);
return EncryptedPassword;
}
protected void btSignup_Click(object sender, EventArgs e)
{
if (tbName.Text != "" && tbEmail.Text != "" && tbUname.Text != "" && tbPass.Text != "" && tbCPass.Text != "" && tbHoneypot.Text == "")
{
if (tbPass.Text == tbCPass.Text)
{
String CS = ConfigurationManager.ConnectionStrings["MyDatabaseConectionString1"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
con.Open();
SqlCommand verifica = new SqlCommand();
verifica.CommandText = "select * from [Users]";
verifica.Connection = con;
SqlDataReader rd = verifica.ExecuteReader();
while (rd.Read())
{
if (rd[1].ToString() == tbUname.Text || rd[3].ToString() == tbEmail.Text)
{
flag = true;
break;
}
}
if (flag == true)
{
if (rd[1].ToString() == tbUname.Text)
{
lblMsg.Text = "Username already exists!";
}
if (rd[3].ToString() == tbEmail.Text)
{
lblMsg.Text = "Email already exists in the database!";
}
}
else
{
SqlCommand cmd = new SqlCommand("insert into Users values('" + tbUname.Text + "','" + EncryptPassword(tbPass.Text) + "','" + tbEmail.Text + "','" + tbName.Text + "','" + tbHoneypot.Text + "','U')", con);
//cmd.ExecuteNonQuery();
lblMsg.Text = "Congratulations! Registration complete!!";
lblMsg.ForeColor = Color.Green;
Response.Redirect("~/Login.aspx");
}
}
}
else
{
lblMsg.Text = "The two passwords don't match!";
}
}
else if (tbHoneypot.Text != "")
{
lblMsg.Text = "Sorry! Bots are not allowed!!";
}
else
{
lblMsg.Text = "All fields are required!!";
}
}
}
}
答案 0 :(得分:2)
取消注释该行
//cmd.ExecuteNonQuery();
如果没有这条线,它将无法正常工作。
顺便说一下,这个:
SqlCommand verifica = new SqlCommand();
verifica.CommandText = "select * from [Users]";
verifica.Connection = con;
SqlDataReader rd = verifica.ExecuteReader();
while (rd.Read())
{
if (rd[1].ToString() == tbUname.Text || rd[3].ToString() == tbEmail.Text)
{
flag = true;
break;
}
}
if (flag == true)
{
if (rd[1].ToString() == tbUname.Text)
{
lblMsg.Text = "Username already exists!";
}
if (rd[3].ToString() == tbEmail.Text)
{
lblMsg.Text = "Email already exists in the database!";
}
}
是一个在DBMS上运行时性能更高的查询。您可能希望将其更改为以下内容:
SELECT [Username], [Email]
FROM [Users]
WHERE [Username] = @Username OR [Email] = @Email
请使用SqlCommand.Prepare()准备查询,而不是查询字符串。你现在这样做的方式,你很容易SQL Injection
根据您的更新,您的真正问题是verifica
和rd
仍在使用con
。你需要处理这些,例如:
using (SqlConnection con = new SqlConnection(CS))
{
con.Open();
bool userNameExists = false;
bool emailExists = false;
using(SqlCommand verifica = new SqlCommand())
{
//Update this query with the hints above
verifica.CommandText = "select * from [Users]";
verifica.Connection = con;
using(SqlDataReader rd = verifica.ExecuteReader())
{
while (rd.Read())
{
if (rd[1].ToString() == tbUname.Text)
{
userNameExists = true;
break;
}
else if (rd[3].ToString() == tbEmail.Text)
{
emailExists = true;
break;
}
}
}
}
if (userNameExists)
{
lblMsg.Text = "Username already exists!";
}
else if (emailExists)
{
lblMsg.Text = "Email already exists in the database!";
}
else
{
//You should update this part too, someone could choose the username
// "x','','U'); DROP TABLE [Users]; --" and do a lot of damage this way
SqlCommand cmd = new SqlCommand("insert into Users values('" + tbUname.Text + "','" + EncryptPassword(tbPass.Text) + "','" + tbEmail.Text + "','" + tbName.Text + "','" + tbHoneypot.Text + "','U')", con);
cmd.ExecuteNonQuery();
lblMsg.Text = "Congratulations! Registration complete!!";
lblMsg.ForeColor = Color.Green;
Response.Redirect("~/Login.aspx");
}
}
图片用户选择名称x','','U'); DROP TABLE [Users]; --
。您的查询会以现在的方式发生什么?
Convert.ToBase64String
不是加密。它是编码,可以很容易地反转。请改用 Hash 。结合上面提到的问题,人们可以轻松阅读所有用户的电子邮件地址和密码(他们当然还有其他帐户,只有这种组合)。
如果只是取消注释一行解决问题而导致另一个问题,那么你就没有修复它 - 你只是引起了另一个问题。
在这种情况下,您的原始问题是
已经有一个与此命令关联的打开DataReader,必须先关闭它。
深思熟虑:您的SqlDataReader
有Close
方法。