3 messaggi dal 21 agosto 2015
Salve a tutti, sto imparando ASP.NET e C# da poco.
Stavo sviluppando una piccola area riservata con funzione di Login al momento.
Vi posto il codice qui sotto:


protected void accedi(object sender, EventArgs e)
    {
        string username=Request.Form["txtuser"];
        string password=Request.Form["txtpass"];

        SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbconn"].ToString());
        
        cn.Open();
        
        
        
        SqlCommand sql = new SqlCommand("SELECT username,password from utenti where username=@username AND password=@password",cn);
        sql.Parameters.AddWithValue("@username",username);
        sql.Parameters.AddWithValue("@password", password);
        SqlDataReader dr=sql.ExecuteReader();

        while(dr.Read()){

            if (username.Equals(dr["username"].ToString()) && password.Equals(dr["password"].ToString()))
            {
               // Session["Utente"] = dr["username"];
                errore_accesso.Text = dr["username"].ToString();
                
                //   Response.Redirect("areariservata.aspx");

            }
            else  {

                errore_accesso.Text = dr["username"].ToString();
                
            }

        }


        
      

    }
}





Il mio problema è che se sbaglio username o password, quindi dovrebbe saltare nell else, la Label errore_accesso non viene visualizzata, mentre nell if (con username e password corretti) funziona.
Grazie mille a tutti ...
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao e benvenuto nel forum!

Quando sbagli username e password, il metodo dr.Read() restituirà false, perché il SqlCommand non ha ottenuto alcuna riga come risultato.
Infatti, nella tua SELECT imponi che username e password corrispondono, ma questo non produrrà risultati se i dati sono sbagliati.
Come conseguenza, il tuo blocco else non andrà mai in esecuzione, perché si trova innestato nel while, all'interno del quale il programma non entra mai dato che dr.Read() era false.

Secondo me, dovresti semplicemente conteggiare il numero di righe ottenute. Se sono 0, vuol dire che il login è fallito.

string username=Request.Form["txtuser"];
string password=Request.Form["txtpass"];
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbconn"].ToString())) {
cn.Open();
  using (SqlCommand sql = new SqlCommand("SELECT COUNT(*) from utenti where username=@username AND password=@password",cn)){
    sql.Parameters.AddWithValue("@username",username);
    sql.Parameters.AddWithValue("@password", password);
    int conteggio = Convert.ToInt32(sql.ExecuteScalar());
    if (conteggio == 0){
      errore_accesso.Text = "I dati di login non sono corretti, riprova";
    } else {
      FormsAuthentication.RedirectFromLoginPage(username, false);
    }

  }
}


Alcune considerazioni:
  • Bravo per aver usato i SqlParameters, ti messo al riparo dalla Sql injection;
  • Se usi dei controlli server come l'asp:Textbox, puoi recuperare l'input dell'utente dalla loro proprietà Text, anziché leggerla dal Request.Form;
  • Non usare la sessione per tracciare gli utenti autenticati. E' un meccanismo obsoleto. Qui trovi maggiori informazioni su un approccio alternativo basato su cookie di autenticazione.
    http://forum.aspitalia.com/forum/post/402579/Best-Pratice-SESSIONE-UTENTE.aspx
  • Nell'esempio di codice ho usato blocchi using che servono a chiudere e distruggere automaticamente sia il SqlCommand che la SqlConnection, anche se si dovesse verificare un errore.
    In generale, andrebbe usato con tutti gli oggetti che implementano IDisposable, ovvero che possiedono un metodo .Dispose()
  • Il metodo ExecuteScalar del SqlCommand che ho usato nell'esempio, restituisce un valore scalare, preso dalla prima colonna della prima riga del risultato. La SELECT così modificata (con un COUNT) ora restituisce sempre un risultato: il conteggio delle righe trovate.


ciao,
Moreno
Modificato da BrightSoul il 21 agosto 2015 18.46 -

Enjoy learning and just keep making
3 messaggi dal 21 agosto 2015
Grazie per tutti questi consigli :)
La select è necessario mettere un count per forza ?
Come posso implementare codice corretto per if else e while senza cadere in queste stupidaggini ?
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,

jqr91 ha scritto:

La select è necessario mettere un count per forza ?

No, non è necessario ma diciamo che è molto conveniente farlo e adatto al tuo scopo.

Avresti comunque potuto risolvere il problema mantenendo la tua query SELECT e usando il metodo ExecuteReader. In questo caso avresti dovuto rimuovere il while e scrivere semplicemente:
//Ricorda che dr.Read() è false se non ci sono righe da leggere
//Quindi la condizione di questo if è: "Se non ci sono righe da leggere..."
if (!dr.Read()){
  errore_accesso.Text = "I dati di login non sono corretti, riprova";
} else {
  FormsAuthentication.RedirectFromLoginPage(username, false);
}

Questa soluzione, rispetto a quella che usa il COUNT e l'ExecuteScalar, richiede che venga creato un DataReader, che è superfluo dato che non andiamo di fatto a leggere i contenuti del record ottenuto (perché sappiamo già che username contiene).

jqr91 ha scritto:

Come posso implementare codice corretto per if else e while senza cadere in queste stupidaggini ?

Devi imparare come usare il debugger di Visual Studio. Grazie ad esso, l'esecuzione della tua applicazione si può interrompere in punti che scegli tu (chiamati "breakpoint", sono pallini rossi che si piazzano al lato sinistro di una riga). Quando l'esecuzione è interrotta, puoi controllare che valore hanno le variabili che hai dichiarato e puoi far avanzare il programma passo-passo. In questo caso ti saresti accorto che dr.Read() era false e che l'esecuzione non entrava nel blocco while. Questi sono già ottimi indizi per capire quale errore si è commesso.

Anche quando acquisirai maggiore esperienza, farai comunque degli errori. Ad uno sviluppatore non si richiede di essere infallibile, ma di saper usare gli strumenti che gli permettono di identificare (meglio se precocemente) e risolvere gli errori che ha commesso.

Ecco alcune guide sul debugger di Visual Studio:
https://msdn.microsoft.com/it-it/library/sc65sadd.aspx
https://msdn.microsoft.com/it-it/library/y740d9d3.aspx
https://youtu.be/7ab4z9u7Q_I?t=75

ciao,
Moreno

Enjoy learning and just keep making
3 messaggi dal 21 agosto 2015
Ciao, grazie davvero di tutto..:)
Ottimo forum e ottimi consigli.

Vedrò come usare il debugger per migliorare il mio codice :)

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.