Страница входа в asp.net. Проблема с запросом?

1

Я хотел бы создать простую страницу входа в asp.net. вот мой код:

protected void Button1_Click(object sender, EventArgs e)
    {
        SqlConnection conn = new SqlConnection();
        conn.ConnectionString = "Data Source=TEST-PC\\SQLSERVER2012;Initial     Catalog=oncf;Integrated Security=True";
        conn.Open();

        string query = "SELECT COUNT(*) FROM Account WHERE acc_username= '" + TextBox1.Text + "' AND acc_password= '" + TextBox2.Text + "'";
        SqlCommand cmd = new SqlCommand(query, conn);
        SqlDataReader myreader = cmd.ExecuteReader();

        int count = 0;
        while(myreader.Read())
        {

            count = count + 1;
        }

        if(count==1)
        {

            Response.Redirect("page2.aspx");
        }
        else
        {
            Label1.Visible = true;
        }

        conn.Close();

    }

Я установил счетчик, чтобы узнать, присутствуют ли введенные учетные данные в БД. Если значение счетчика равно 1, логин будет успешным. В противном случае отображается метка с сообщением об ошибке! Однако, что бы я ни вводил в качестве входных данных в текстовом поле имени пользователя и входа, он всегда перенаправляет меня на другую страницу! На данный момент меня беспокоит не аспекты безопасности, я просто хочу проверить этот простой код, я не вижу никаких проблем с кодом, но все равно он не работает, он сводит меня с ума...

  • 1
    Мой совет, даже несмотря на тот факт, что такого рода проблемы НЕПРЕРЫВНЫ, зная, что мы не знаем, что вы вводите в своей форме, и без информации о вашей базе данных, вы должны выполнить свою программу, а затем выполнить свой запрос, чтобы увидеть, есть ли у вас тот же результат.
  • 1
    Вы должны использовать параметризованные запросы , и вы не должны хранить незашифрованные пароли
Теги:

5 ответов

2
Лучший ответ

Проблема, с которой вы столкнулись, связана с тем, что запрос followinq всегда возвращает одну строку, даже если в базе данных нет соответствия:

SELECT COUNT(*) FROM Account WHERE acc_username=....

Если совпадения нет, вы получите строку с одним столбцом, значение 0. Вы проверяете количество возвращаемых строк, когда вы должны просто проверять возвращаемое значение.

Используйте это вместо этого

    int count = Convert.ToInt32(cmd.ExecuteScalar());

    if(count==1)
    {

        Response.Redirect("page2.aspx");
    }
    else
    {
        Label1.Visible = true;
    }

Я знаю, что вы сказали, что не хотите советов по безопасности, но просто для того, чтобы быть уверенным:

  • Не храните пароли обычного текста в базе данных. Всегда используйте их, используя соль.
  • Не используйте конкатенацию строк при создании sql. Используйте параметры.
  • 0
    Я получаю это Исключение типа «System.InvalidOperationException» произошло в System.Data.dll, но не было обработано в коде пользователя
  • 0
    Используйте Convert.ToInt32 вместо приведения.
Показать ещё 6 комментариев
3

Причина, по которой вы всегда перенаправляетесь, заключается в том, что ваш читатель всегда возвращает 1 строку, есть ли совпадение или нет. Если в вашей базе данных есть совпадение, запрос вернется

(no column name)
---------------
1

Если нет совпадения, он вернется:

(no column name)
---------------
0

В любом случае myreader.Read() вернет true, и вы увеличите count в этой части:

while(myreader.Read())
{

    count = count + 1;
}

if(count==1)
{

    Response.Redirect("page2.aspx");
}

Вместо проверки того, возвращает ли запрос строки, вы можете получить значение счетчика, используя SqlCommand.ExecuteScalar(). В дополнение к этому я бы сделал еще три изменения:

1. Использовать параметризованные запросы

Это не просто проблема безопасности, параметризованные запросы могут использовать кэшированные планы, тогда как если вы объединяете параметры в запрос, тогда новый план будет скомпенсирован для каждого нового значения переменной. Кроме того, параметризованные запросы более строго типизированы, и вам не нужно избегать таких вещей, как O'shea чтобы ваша дополнительная цитата не O'shea запрос.

2. Шифровать пароли

Это напрямую связано с безопасностью, поэтому действительно следует упускать из виду, как ваш запрос, чтобы не комментировать безопасность, ОДНАКО, этот ответ не только для вашей выгоды, а половина ответа, скорее всего, будет прочитана кем-то в будущем, кто может или может не знать о рисках хранения паролей с открытым текстом. В этом ответе есть простой метод шифрования.

3. Добавьте блоки к вашему коду

Небольшое изменение, но когда у вас есть объекты, реализующие IDisposable, рекомендуется using блок using чтобы убедиться, что они утилизируются должным образом.

Таким образом, вы можете:

string password = SomeStaticClass.Encrypt(TextBox2.Text);
string connectionString = "Data Source=TEST-PC\\SQLSERVER2012;Initial     Catalog=oncf;Integrated Security=True";
string query = "SELECT UserCount = COUNT(*) FROM Account WHERE acc_username= @UserName AND acc_password= @Password";

using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
    connection.Open();
    command.Parameters.Add("@UserName", SqlDbType.VarChar, 50).Value = TextBox1.Text;
    command.Parameters.Add("@Password", SqlDbType.VarChar, 50).Value = password;

    int count = Convert.ToInt32(command.ExecuteScalar());

    if(count==1)
    {
        Response.Redirect("page2.aspx");
    }
    else
    {
        Label1.Visible = true;
    }
}
1

Вы всегда должны использовать Paremeterized query. С помощью параметров в операторах SQL

string username=TextBox1.Text;
string password=TextBox2.Text;
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=TEST-PC\\SQLSERVER2012;Initial     Catalog=oncf;Integrated Security=True";
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Account WHERE acc_username=@username and 
AND acc_password=@password", conn);

cmd.Parameters.AddWithValue("@username",username);
cmd.Parameters.AddWithValue("@password",password);

SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
       if (dt.Rows.Count > 0)
        {
          Response.Redirect("page2.aspx");
        }
        else
        {
         Label1.Visible = true;
        }
  • 0
    Я получаю ArgumentException в da.Fill (DT)
  • 0
    @Simon Я обновил проверить сейчас
Показать ещё 1 комментарий
1

не используйте ExecuteReader когда вы хотите вернуть одно значение, используйте ExecuteScalar:

int count = int.Pares(cmd.ExecuteScalar().toString());

if(count >= 1)
{

    Response.Redirect("page2.aspx");
}
else
{
    Label1.Visible = true;
}
0

Попробуйте добавить if (myreader.HasRows) до этого while(myreader.Read())

Ещё вопросы

Сообщество Overcoder
Наверх
Меню