Laden...

Passwortabfrage Mysql

Erstellt von flippi vor 17 Jahren Letzter Beitrag vor 17 Jahren 4.079 Views
F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren
Passwortabfrage Mysql

Hallo!

Habe ein Problem bei einem Passwortabgleich zwischen einer Mysql-DB und einem C# Prog.. Ich schreibe gerade ein Programm. Bei dem sich ein Benutzer mit Benutzernamen und Kennwort anmelden kann. Die Benutzernamen und Kennwörter sind in einer Mysql-Datenbank abgelegt. Ich habe hier auf MyCsharp schon einige Threads zu diesem Thema gefunden und auch eine anscheinend gute Lösung. Nur klappt diese nicht so ganz bei mir. Ich finde aber den Fehler nicht. Denke mal das ist nur eine Kleinigkeit und ich stelle mich einfach nur zu dumm an. Hier der Quellcode zur Überprüfung des Benutzernamens und des Kennwortes. Wenn ich Debugge, bekomme ich zwei Fehler: Verwendung der nicht zugewiesenen lokalen Variablen "Benutzername" und die gleiche mit "Benutzerpasswort". Die Variablen habe ich aber eigentlich zugewiesen (Denke ich zumindest). Für mögliche Lösungsvorschläge und oder Beispiele bin ich sehr dankbar. Bin absoluter Neuling auf diesem Gebiet.

private void btnOK_Click(object sender, EventArgs e)
        {
        string str_username = tbBN.Text;
        string str_Kennwort = tbPW.Text;
        
       
            //Verbindung
        string conStr = "server=localhost;uid=root;pwd=flippi;database=lager;Port=3306";
        MySqlConnection MysqlConn = new MySqlConnection(conStr);
        
            //Reader erzeugen
        MySqlDataReader dbReader = null;
        MySqlCommand cmd = new  MySqlCommand();
        cmd.Connection = MysqlConn;
        cmd.Parameters.Add("@Benutzername","benutzername");
        cmd.Parameters.Add("@Benutzerpasswort","benutzerpasswort");
        cmd.CommandText = "SELECT benutzername AS Benutzername, benutzerpasswort AS Benutzerpasswort FROM benutzer where benutzername = " + this.tbBN.Text +"";

            try
            {
                MysqlConn.Open();

              //  str_benutzername = "benutzername".ToString();
              
            dbReader = cmd.ExecuteReader();
            string benutzername;
            string benutzerpasswort;
            while(dbReader.Read())
            {
            benutzername = (string)dbReader.GetValue(2);
            benutzerpasswort = (string)dbReader.GetValue(3);//Spalte in tabelle
            }
            if (str_username == benutzername && str_Kennwort == benutzerpasswort)
                {
                    MessageBox.Show("OK");
                }
                else
                {
                    MessageBox.Show("Falsches Kennwort oder Benutzername");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            MysqlConn.Close();
        }

//edit: C#-Code-Tags richtig gestellt!!!

N
750 Beiträge seit 2004
vor 17 Jahren

Die Variablen habe ich aber eigentlich zugewiesen (Denke ich zumindest).

ja, die werden aber nur zugewiesen, wenn deine Schleife

while(dbReader.Read())
{
  benutzername = (string)dbReader.GetValue(2);
  benutzerpasswort = (string)dbReader.GetValue(3);//Spalte in tabelle
}

auch durchlaufen wird, ansonsten nicht.

Ich vermute mal, das daher deine Fehlermeldung kommt!!

nils

?( wer suchet, der findet auch! :]

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Hi Nils!

Danke für die rasche Antwort. Kommt mir auch logisch vor, wie du es sagst... Aber wie helfe ich dem ab? Andere Schleife: do{} while?

Gruß Philipp

M
104 Beiträge seit 2005
vor 17 Jahren

Hallo flippi,

cmd.CommandText = "SELECT benutzername AS Benutzername, benutzerpasswort AS Benutzerpasswort FROM benutzer where benutzername = " + this.tbBN.Text +"";

Was passiert eigentlich, wenn ich als Benutzer folgendes (oder schlimmeres) in die tbBN eintrage:

 'Meier'; delete from benutzer;

Wenn Du schon Parameter zuweist, solltest Du diese auch benutzen....

while(reader.Read())....

Zuerst würde ich prüfen, ob überhaupt ein Datensatz gefunden wurde (

reader.HasRows()

Ich hoffe, dass in der Db die Tabelle benutzer einen unique-Constraint auf den benutzernamen hat; wenn nicht kann es passieren. dass Du zwei oder mehr Datensätze zurück bekommst -> welcher Benutzer soll denn angemeldet werden....

Grüße
Morpheus

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Hallo Morpheus!

Dann wird der Benutzer Maier gelöscht, aber so weit will ich noch nicht denken. Es soll ersteinmal nur funktionieren. Oder hast du auf die Schnelle ein Beispiel parat? Aber wie gesagt, es soll sich erst einmal jemand anmelden können (egal ob mit Sicherheitsrisiko oder ohne). Wenns funzt, schau ich am Ende nach der Perfektion...

Gruß
flippi

3.825 Beiträge seit 2006
vor 17 Jahren

Hallo Flippi,

statt


string benutzername;
string benutzerpasswort;
...

schreibe


string benutzername = "";
string benutzerpasswort = "";
...

Wenn Du Variablen verwendest müssen Sie auch vorher zu 100% definiert sein. Und das ist bei Dir nicht der Fall, wenn nämlich kein Datensatz gefunden wurde.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

M
104 Beiträge seit 2005
vor 17 Jahren

Original von flippi
Dann wird der Benutzer Maier gelöscht, aber so weit will ich noch nicht denken. ... (egal ob mit Sicherheitsrisiko oder ohne). Wenns funzt, schau ich am Ende nach der Perfektion...

Hallo flippi,

das von mir genannte Problem löscht Dir nicht den Benutzer "Meier" sondern die gesamte Benutzertabelle! Das hat nichts mit Perfektion zu tun, sondern ist einfach nur fahrlässig.

aber zurück zum Thema:

Das gehashte Passwort befindet sich in der dritten Spalte. Das vom Benutzer eingegebene PW wird dieser Methode übergeben.


public bool CheckCredential(string username, string hashedPassphrase) {
using (DbCommand selectUser = factory.CreateCommand()) {
	selectUser.CommandText = "SELECT * FROM USERDATA WHERE USERNAME=@username";
	selectUser.Connection = connection;
	DbParameter param = selectUser.CreateParameter();
	param.DbType = DbType.String;
	param.ParameterName = "@username";
	param.Value = username;
	selectUser.Parameters.Add(param);
	connection.Open();
	DbDataReader reader = selectUser.ExecuteReader();
	if (reader.HasRows) {
		if (reader.Read()) {
			if (hashedPassphrase == reader.GetString(2)) {
				return true;
			}
		}
	}
	return false;
}

Gruß
Morpheus

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Hi Morpheus,

erstmal vielen Dank für deine Hilfe. Wenn ich dich richtig verstehe, sollte der Code bei mir dann so aussehen:

public bool CheckCredential(string username, string hashedPassphrase) {
using (DbCommand selectUser = factory.CreateCommand()) {
    selectUser.CommandText = "SELECT * FROM benutzer WHERE Benutzername=@Benutzername";
    selectUser.Connection = connection;
    DbParameter param = selectUser.CreateParameter();
    param.DbType = DbType.String;
    param.ParameterName = "@Benutzername";
    param.Value = username;
    selectUser.Parameters.Add(param);
    connection.Open();
    DbDataReader reader = selectUser.ExecuteReader();
    if (reader.HasRows) {
        if (reader.Read()) {
            if (hashedPassphrase == reader.GetString(2)) {
                return true;
            }
        }
    }
    return false;
}

Aber wo füge ich den Code ein, dass es funzt? Danach hab ich ja trotzdem noch das Problemchen mit den zugewiesenen Variablen, oder.

Gruß Flippi

//Edit: C# code-tags ergänzt!! (bitte auf das Ende-Tag achten!)

M
104 Beiträge seit 2005
vor 17 Jahren

Hallo flippi,

das mit den Variablen hat ja schon BerndFfm geschrieben.

Die Methode CheckCredentials ist, wie der Name schon sagt eine Methode....

...
if (CheckCredential(str_username, str_Kennwort))
{
  MessageBox.Show("OK");
}
else
{
   MessageBox.Show("Falsches Kennwort oder Benutzername");
}
...

Gruß
Morpheus

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Vielen vielen Dank an BerndFfm und Morpheus, ich muss jetzt leider erst einmal unterbrechen, ich versuche die von euch genannten Tipps in die Tat umzusetzen. Ich schreibe morgen Vormittag wieder. Hoffe es funktioniert dann. Wünsche euch noch einen schönen Abend.

Liebe Grüße

Flippi

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Hallo!

Hab da noch paar Problemchen, wenn ich einen Namen bei Benutzername eingebe, erhalte ich immer die Fehlermeldung unknown column 'Name' in 'where clause', obwohl der Name in der Tabelle benutzer vorhanden ist. Jemand eine Ahnung, wie ich das beseitigen kann???

Danke Morpheus, bekomme aber die Funktion leider nicht zum Laufen.

Bekomme beim Debuggen folgende Fehlermeldungen

Fehler 1 Der Name "Factory" ist im aktuellen Kontext nicht vorhanden. C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Visual Studio 2005\Projects\test1vdb\test1vdb\Form1.cs 88 47 test1vdb

Fehler 2 "MySql.Data.MySqlClient.MySqlConnection" ist ein(e) "Typ", wird aber wie ein(e) "Variable" verwendet. C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Visual Studio 2005\Projects\test1vdb\test1vdb\Form1.cs 91 41 test1vdb

Fehler 3 Für das nicht statische Feld, die Methode oder die Eigenschaft "System.Data.Common.DbConnection.Open()" ist ein Objektverweis erforderlich. C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Visual Studio 2005\Projects\test1vdb\test1vdb\Form1.cs 97 17 test1vdb

Hab deine Funktion folgendermaßen umgeschrieben:

 public bool CheckCredential(string username, string hashedPassphrase)
        {
            using (MySqlCommand selectUser =  Factory.CreateCommand())
            {
                selectUser.CommandText = "SELECT * FROM benutzer WHERE Benutzername=@Benutzername";
                selectUser.Connection = MySqlConnection;
                MySqlParameter param = selectUser.CreateParameter();
                param.DbType = DbType.String;
                param.ParameterName = "@Benutzername";
                param.Value = username;
                selectUser.Parameters.Add(param);
                MySqlConnection.Open();
                MySqlDataReader reader = selectUser.ExecuteReader();
                if (reader.HasRows)
                {
                    if (reader.Read())
                    {
                        if (hashedPassphrase == reader.GetString(2))
                        {
                            return true;
                        }
                    }
                }
                return false;
            }

        }

Den Namen Factory gibt es bei mir nicht, es gibt nur MySqlClientFactory und da nur Equals, Instance und ReferenceEquals.

Danke im Voraus für alle Antworten.

Gruß Flippi

//edit: C# Code TAgs richtig gestellt!! (Bitte auf das Ende-Tag achten!!!)

3.825 Beiträge seit 2006
vor 17 Jahren

Hallo Flippi,

das mit dem Factory brauchst Du nur, wenn Du dein Programm mit verschiedenen Datenbanksystem betreiben willst (und nicht mal dann 😉 )

Wenn Dein Programm (erstmal) nur mit MySQL laufen soll dann nimm Deinen Code vom ersten Posting.

Wenn doch DBFactory musst Du "using System.Data.Common" einbinden und MySQL muss als DataBaseprovider eingetragen sein (app.conf oder so). Das sollte der mySQL Treiber aber automatisch machen bei der Installation.

Der Code sieht dann so aus :


DbConnection conn = null;
DbProviderFactory factory;
factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
conn = factory.CreateConnection();

" ... ist ein(e) "Typ", wird aber wie ein(e) "Variable" verwendet" : Dann hast Du meistens Klammern vergessen oder zuviele hingeschrieben.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Hi BerndFfm!

Aber Morpheus hat ja gemeint, dass es fahrlässig ist, wenn ich nur den ersten Code benutze, da man beim eintippen des Users ja ein SQL-Kommando mit schreiben könnte und so die ganze Tabelle gelöscht würde (so hab ich ihn zumindest verstanden). Die Anwendung soll und muss nur auf einer MySql-Datenbank laufen.

Meinst du also, ich sollte die komplette Funktion (CheckCredential) nicht verwenden?

Aber auch wenn ich sie nicht verwende, das Problem mit der Abfrage besteht dennoch. Ich habe den Fehler schon im Internet gesucht, da steht, dass man die Select...Where...Clausel in eine Join...Clausel umwandeln soll, nur weiss ich nicht genau wie. Weist du das evtl.?

Bis jetzt sieht sie so aus:

 cmd.CommandText = "SELECT benutzername AS Benutzername, benutzerpasswort AS Benutzerpasswort FROM benutzer WHERE benutzername = " + this.tbBN.Text + "";

[/csharp]

N
750 Beiträge seit 2004
vor 17 Jahren

Aber Morpheus hat ja gemeint, dass es fahrlässig ist, wenn ich nur den ersten Code benutze, da man beim eintippen des Users ja ein SQL-Kommando mit schreiben könnte und so die ganze Tabelle gelöscht würde (so hab ich ihn zumindest verstanden).

damit meint er SQL-Injection --> bitte bei wikipedida nachschlagen, da eine Diskussion darüber hier nicht weiterhilft. Danke!

nils

?( wer suchet, der findet auch! :]

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Alles klar Nils!

Habs gerade nachgeschlagen. Danke für den Hinweis.

Dennoch bleibt mein Problem offen.

Gruß

Flippi

3.825 Beiträge seit 2006
vor 17 Jahren

Nimm doch erstmal deinen zuerst geposteteten Code und ändere ihn wie ich vorgeschlagen habe. SQL-Injection kannst Du ja später verhindern.

Statt

if (reader.HasRows) { if (reader.Read()) {

reicht

if (reader.Read()) {

oder

while (reader.Read()) {

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

Jo, Danke Bernd!

Das klappt, aber der String zur SQL-Datenbank nicht. Hast du da auch ne Idee?

Grüße
Philipp

F
flippi Themenstarter:in
19 Beiträge seit 2006
vor 17 Jahren

😁
Wunderbar!

Das mit der Fehlermeldung hat funktioniert, hab den String für die Datenbank abgeänder in ...like'"...'"

und der Index vom DataReader war auch falsch (von 2 auf 0 und von 3 auf 1)

Danke

Grüße
Philipp