Autor Beitrag
mkRE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: So 17.01.16 17:22 
Hallo Yankyy02,

ich habe gedacht das ich dieses Wochenende ans Programmieren gehen kann leider hat es nicht geklappt :(.
Danke für den Tipp oben wie versprochen halte ich dich auf dem Laufenden ob ich damit klar gekommen bin.

Das will ich hinbekommen und die Datenbank Testanwendung abschließen um an ein Größeres Projekt ranzugehen was ich plane.

P.S. die Windows Administrations Beispielanwendung ist klasse und auf jedenfall findet diese Variante auch Ihren nutzen!!

Viele Grüße
mkRE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Sa 30.01.16 01:52 
Hallo Yankyy02,

ich bin heute mal endlich an das Projekt ran gekommen, momentan viel zu tun :-)
Es funktioniert nun alles so wie es gedacht war.
Ich habe zum Probieren als probe erstmal in der Datenbank das Administationsfeld Admin oder User als string gewählt.

Es funktioniert zwar alles, aber ich habe ein problem gehabt beim geöffneten DataReader zwei mal ein Command auszuführen.
Weil ich zuerst einmal prüfen wollte ob die Benutzerdaten Name und Passwort ok sind und dann im nächsten Schritt ob es sich um einen Admin handelt.
Dazu musste ich die MARS Methode nutzen, jedoch funktioniert diese nur bei SQL Datenbanken wie ich gelesen habe.

Meine Frage nun dazu ist, wie könnte man es noch anders lösen?

Hier einmal der Code der Methode der Klasse AccesControl:


ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
        private static string GetConnectionString()
        {
            return "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\UserData.mdf;Integrated Security=True;Connect Timeout=30; MultipleActiveResultSets=True";
        }


        public bool Access(string username, string password)
        {
            SqlDataReader re_access = null;
            StringBuilder errorMessages = new StringBuilder();
           
            using (SqlConnection con = new SqlConnection(@GetConnectionString()))
            {
                try
                {
                    SqlCommand cmd = new SqlCommand("Select * From Usertable where Username='" + username + "' and Password = '" + password + "'", con);
                    SqlCommand cmd_access = new SqlCommand("Select * From Usertable where Username='" + username + "' and Password = '" + password + "' and Access='" + "Admin" + "'", con);

                    con.Open();

                    using (SqlDataReader re = cmd.ExecuteReader())
                    {
                        while (re.Read())
                        {
                            access = true;

                            re_access = cmd_access.ExecuteReader();
                            using (re_access)
                            {
                                while (re_access.Read())
                                {
                                    isAdmin = "Admin";
                                }
                            }
                        }
                    }

                    con.Close();
                }
                catch (SqlException ex)
                {
                    for (int i = 0; i < ex.Errors.Count; i++)
                    {
                        errorMessages.Append("Index #" + i + "\n" +
                            "Message: " + ex.Errors[i].Message + "\n" +
                            "LineNumber: " + ex.Errors[i].LineNumber + "\n" +
                            "Source: " + ex.Errors[i].Source + "\n" +
                            "Procedure: " + ex.Errors[i].Procedure + "\n");
                    }
                    access = false;
                    System.Windows.Forms.MessageBox.Show(errorMessages.ToString());
                    con.Close();
                }
            }
            return access;           
        }


und hier ein Auszug wo die Methode angewendet wird bzw. wofür:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
private void btnAnmelden_Click(object sender, EventArgs e)
        {

            AccessControl access = new AccessControl();

                if (access.Access(txtUsername.Text, txtPasswort.Text) && AccessControl.IsAdmin == "Admin")
                {
                    frmBTGDatabase.label_1.Text = "Angemeldet Admin";
                    frmBTGDatabase.button_1.Enabled = true;
                    frmBTGDatabase.button_2.Enabled = true;
                    frmBTGDatabase.button_3.Enabled = true;
                    frmBTGDatabase.button_4.Enabled = true;
                    frmBTGDatabase.button_5.Enabled = true;
                    frmBTGDatabase.button_6.Enabled = true;
                    this.Close();
                }
                else if (access.Access(txtUsername.Text, txtPasswort.Text))
                {
                    frmBTGDatabase.label_1.Text = "Angemeldet User";
                    frmBTGDatabase.button_1.Enabled = true;
                    frmBTGDatabase.button_2.Enabled = true;
                    frmBTGDatabase.button_3.Enabled = true;
                    frmBTGDatabase.button_4.Enabled = true;
                    frmBTGDatabase.button_5.Enabled = true;
                    this.Close();
                }
                else
                {
                    MessageBox.Show("Benutzername oder Passwort falsch!");
                    this.Close();
                }
        }


P.S. Es handelt sich hier um eine frühere Idee, jedoch finde ich deine Idee besser bei Jeder Aktion zu prüfen ob die Admin oder User Berechtigungen hat.

Viele Grüße
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 30.01.16 13:12 
a.) Wieso benutzt du 2 DataReader? Das erste Statement würde dir in den Daten bereits den Inhalt des Access Feld liefern du müsstest es einfach nur auslesen (re["Access"]).
b.) Wieso benutzt du überhaupt einen DateReader? Erwartest du von der Abfrage jemals mehr als 1 Ergebnis?
c.) Für die Technik erstmal weniger relevant. Aber willst du wirklich das Passwort als Klartext ablegen? Das solltest du, sobald das so funktioniert wie du willst, umstellen.

Unter der Annahme das du nur wissen willst ob der User Zugang bekommt und wenn ja welchen dann würde ich das folgendermassen machen.
a.) Den Zugang über strings zu regeln finde ich merkwürdig ich würde einen Enum verwenden und in der Datenbank als Zahlentyp (access also als nicht nullable int) darstellen. Das funktioniert aber mit strings auch.
b.) Das ErrorHandling gehört für mich nicht in deine AccessControl Klasse rein. Insbesondere wenn das Errorhandling ein einfaches MessageBox Show ist (meiner Meinung nach also eher kein ErrorHandling sondern ein ErrorAufUserAbwälzing ;) ). Die Methode/Klasse ist eigentlich unabhängig von der UI Technik. Sie würde genauso in einer Webanwendung funktionieren. Di eunabhängig sollte man nicht durch unnötige Abhängigkeiten kaputt machen. Was Sinn machen kann wäre das fangen der SqlException und umpacken in eine eigene die die Aufbereitung der ErrorMEssage beherrscht und dann diese Exception werfen anstatt der SqlException.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
[Flags]
public enum Access
{
    None = 0x0,
    Login = 0x1,
    Admin = 0xFF
}

public static Access? GetAccess(string username, string password)
{
    using (var con = new SqlConnection(GetConnectionString()))
    {
        con.Open();
        using (var cmd = con.CreateCommand())
        {
            cmd.CommandText = @"Select Access From Usertable where Username=@username and Password=@password";
            cmd.Parameters.AddWithValue("@username", username);
            cmd.Parameters.AddWithValue("@password", password);

            int? result = cmd.ExecuteScalar() as int?;

            if (!result.HasValue)
                return null// login failed no access

            return (Access)result.Value;
        }
    }
}

// Aufruf
var access = AccessControl.GetAccess(txtUsername.Text, txtPasswort.Text);

if (access.HasValue)
{
    if (access.Value.HasFlag(Access.Admin))
    {
        // admin
    }
    else
    {
        // anderer Zugang
    }
}
else
{
    // kein Zugang 
}

Für diesen Beitrag haben gedankt: mkRE
mkRE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Sa 30.01.16 20:31 
Hallo Ralf,

vielen Dank für deine Antwort hier kommen meine Antworten zu deinen Fragen:

a.) Ich hab es noch nicht herausgefunden wie ich aus einem DataRead einzelne Werte zusätzlich abfragen kann z.B. in dem Fall den Wert in der Datenbank Spalte Access.
So kam ich zuerst auf die Idee zwei command Befehle zu schreiben. Dabei bin ich auf das Problem gestoßen das ich den Reader nicht zwei mal nacheinander anwenden konnte.
So habe ich im Netz nach einer möglichkeit gesucht und diese MARS Methode auf den Seiten von Windows gefunden. Dort wurde auch mit zwei DataReader ein Beispiel gezeigt. Das war der Grund.
Wie frage ich den aber Einzelne Werte ab bzw. das einfache auslesen (re["Access"]).
In erster Linie möchte ich einmal nur sehen ob der User auch Adminrechte hat, der Lösungsvorschlag von Yankyy02 gefällt mir sehr, dort war aber die rede von einem Bool, das wollte ich auch noch
nachträglich so realisieren.
[i]
Gucke heute Abend nochmal danach in dem Program wo du es genau meinst. Mir sind die Befehle noch nicht ganz klar bzw. vielleicht bei den vielen Hilfen übersehen.
b.) Bei dieser Anwendung erwarte ich nur 1 Ergebnis. Den DataReader habe ich gewählt, weil alle Beispiele die ich vor ca. 2 Jahren zum Thema Benutzeranmeldung gefunden habe den DataReader verwendet
haben und nun ist das bei mir hängen geblieben.
c.)Meinst du den Text als Klartext in der Datenbank? Bei der Eingabe über die Anwendung ist der Passwort Text nicht erkennbar. In der Datenbank momentan ja jedoch möchte ich das Passwort nicht als
Klartext zu erkennen geben und in Form von Sternchen anzeigen lassen. Hoffe ich habe deine Frage richtig verstanden?


Ja genau hierbei möchte ich nur wissen ob der User Zugang hat und natürlich für welchen Bereich.
Es gibt so viele Möglichkeiten und dein Vorschlag ist auch eine gute Idee. Leider fallen mir nicht alle möglichen Methodiken ein die man nutzen könnte es gibt sicherlich auch noch ganz andere Wege.
(Ich frage mich immer woher ihr das alles wisst :) :oops: ist positiv gemeint).

Zu dem Error Handling danke für den Tipp, habe mir schon gedacht das es jemand anmeckert das es sich in der AccessControl Klasse befindet :D, muss mir noch was dazu ausdenken.

Viele Grüße

mkRE
mkRE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Sa 30.01.16 20:43 
Ich sehe gerade wer lesen kann ist klar im Vorteil :-) Yankyy02 hat es auch schon beschrieben mano tut mir leid.
Also so kann ich einzeln auf Werte im Reader abfragen.

Beispiel von Yankyy02

ausblenden C#-Quelltext
1:
AccessControl.IsAdmin = Convert.ToBoolean(reader["Administrator"]);					


Ich muss mich vielmals entschuldigen bei euch beiden, das ich das gestern übersehen habe.

Viele Grüße
mkRE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 98



BeitragVerfasst: Mi 03.02.16 01:00 
Hallo zusammen und danke besonders an Yankyy02 und Ralf Jansen für die Hilfe bei dem Thema.

Das ganze funktioniert jetzt und ist für mich für die Anwendung ausreichend.
Ich habe es bei der Anwendung isAdmin bei einem String gelassen jedoch werde ich das bei einer nächsten Anwendung mit einem Bool Feld erledigen.

Unten habe ich mal den Code der AccessControl Klasse beigefügt, vielleicht interessiert es ein paar Einsteiger die einen Lösungsansatz suchen.
Für weitere Tipps oder Anmerkungen dazu würde ich mich freuen.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
namespace BTG_Database
{
    class AccessControl
    {
        private static bool access = false;
        private static string isAdmin = "";

        private bool error = false;
        private string errormessage = "";
        
        public static bool AccessSuccessfull
        {
            get { return access; }
        }

        public static string AccessIsAdmin
        {
            get { return isAdmin; }
        }

        public bool AccesError
        {
            get { return error; }
        }

        public string AccessErrorMessage
        {
            get { return errormessage; }
        }

        private static string GetConnectionString()
        {
            return "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\UserData.mdf;Integrated Security=True;Connect Timeout=30";
        }

        public bool Access(string username, string password)
        {
            
          StringBuilder errorMessages = new StringBuilder();
          using(SqlConnection con = new SqlConnection(@GetConnectionString()))
          {
            try
            {                    
                    SqlCommand cmd = new SqlCommand("Select * From Usertable where Username='" + username + "' and Password = '" + password + "'", con);
                    con.Open();

                    SqlDataReader re = cmd.ExecuteReader();
                
                if (re.Read())
                    {
                        
                        access = true;
                        isAdmin = Convert.ToString(re["Access"]);
                    }
                    else
                    {
                        access = false;
                    }

                    con.Close();

             }
            catch (SqlException ex)
             {
               error = true;
               access = false;
               con.Close();
   
               for (int i = 0; i < ex.Errors.Count; i++)
               {
                   errorMessages.Append("Index #" + i + "\n" +
                       "Message: " + ex.Errors[i].Message + "\n" +
                       "LineNumber: " + ex.Errors[i].LineNumber + "\n" +
                       "Source: " + ex.Errors[i].Source + "\n" +
                       "Procedure: " + ex.Errors[i].Procedure + "\n");
               }               
               errormessage = errorMessages.ToString();              
            }
          }
                    return access;           
        }

        public void Logout()
        {
            isAdmin = "";
            access = false;
        }
    }
}


Viele Grüße und Danke
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 03.02.16 10:36 
Noch ein Tipp:
Benutze dringendst SqlParameter (anstatt dem Zusammensetzen von SQL-Strings mittels ') - Stichwort: SQL-Injection!

Für diesen Beitrag haben gedankt: mkRE