Jak poprawić tą pętlę?

0

Chce zrobic symulacje logowania. Mam liste uzytkownikow metoda w klasie uzytkownicy, ktora sprawdza poprawnosc hasel. Jest ona na pewno dobra. Problem w tym, ze program przy logowaniu zawsze bierze pod uwage tylko pierwszego uzytkownika. Ma ktos moze pomysl jak brac pod uwage wszystkich i otwierac nastepne okno(logowac sie tylko w przypadku gdy haslo i login z listy sa poprawne?)

     string Login = this.txtLogowanie.Text;
            string Haslo = this.boxHaslo.Password;
            bool[] TablicaPrawdy = new bool[ListaUzytkownikow.Count];
            int i = 0;
            foreach (var element in ListaUzytkownikow)
            {
                   bool wynik = element.SprawdzamLogowanie(Login, Haslo);          //Sprawdza warunek prawdziwosci hasla i loginu
                   TablicaPrawdy[i] = wynik;
                   i++;

            }
            // dobrze dotad 
           for(int j=0;j<ListaUzytkownikow.Count;j++)
           {
               if (TablicaPrawdy[j] == true)
               {

                   this.Hide();
                   Window1 ob1 = new Window1();
                   ob1.Show();
                   break;
               }

               else
               {
                   MessageBox.Show("Wpisales nie poprawne dane !");
                   break;
               }
           }
1

Skoro masz break w if to nie dziwne, że tylko raz Ci otwiera okno. Po prostu jak znajdzie dobry element to otwiera okno i wychodzi Ci z pętli. Dodatkowo nie potrzebujesz dwóch pętli. W jednej pętli możesz sprawdzać poprawność danych i jeśli jest ok od razu wyświetlaj okno. W takim wypadku TablicaPrawdy jest Ci w ogóle nie potrzebna

2

Strasznie tu nakombinowałeś. Po pierwsze - po co używasz pętli foreach dla tablicy, której wartości zmieniasz? Używaj normalnie pętli for:

for(int i = 0; i < ListaUzytkownikow.Count; i++)
  TablicaPrawdy[i] = ListaUzytkownikow[i].SprawdzamLogowanie(Login, Haslo);

To jest cała pierwsza pętla.

Poza tym za bardzo nie wiesz chyba, co chcesz osiągnąć. Najpierw próbujesz zalogować każdego użytkownika przekazanym JEDNYM loginem i JEDNYM hasłem. Potem dla tego każdego sprawdzasz, czy udało się zalogowac, czy nie. I jeśli udało się zalogować użytkownika o indeksie n, to dostaniesz n-1 informacji o niepoprawnym logowaniu. Chyba nie to chciałeś osiągnąć, co?

Prawidłowe logowanie polega na tym, że:

  1. Sprawdzasz w bazie danych, czy przekazany login i hasło się zgadzają. To wszystko. Jeśli nie masz SQLowej bazy, tylko trzymasz to np. w liście, to wtedy coś w ten deseń:
bool UserLogin(string login, string pass)
{
  User u = userList.Find(u=> u.Login == login);
  return u.Pass == pass;
}

Ta metoda znajduje na liście usersList użytkownika o przekazanym loginie. UWAGA! Kod zakłada, że taki użytkownik na pewno istnieje. W rzeczywistym rozwiązaniu musisz potem sprawdzić, czy u != null zanim sprawdzisz hasło (jesli nie ma takiego usera, czyli u == null, wtedy oczywiście zwracasz false).
Druga linijka sprawdza hasło użytkownika z tym przekazanym w parametrze. Jeśli się zgadzają, to zwraca true.

0

Wpisales nie poprawne dane

Powinno być

"Wpisales niepoprawne dane"

2

Nie sprawdza się wszystkich użytkowników! Wyobraź sobie, że masz ich sto tysięcy i naraz loguje się ich tysiąc. Będą musieli czekać po kilka minut na zalogowanie się. Wyszukujesz w bazie (czy też jakieś jej namiastce w postaci listy czy hash-table (Dictionary)) po loginie, potem dla jednego znalezionego użytkownika (o ile taki będzie) weryfikujesz hasło i już.

@Juhas:

Juhas napisał(a):

Prawidłowe logowanie polega na tym, że:

  1. Sprawdzasz w bazie danych, czy przekazany login i hasło się zgadzają. To wszystko. Jeśli nie masz SQLowej bazy, tylko trzymasz to np. w liście, to wtedy coś w ten deseń:
bool UserLogin(string login, string pass)
{
User u = userList.Find(u=> u.Login == login);
return u.Pass == pass;
}

Hasło weryfikuje się inaczej, bo w bazie danych nie trzyma się hasła, tylko jego hash i salt. Rozumiem, że pytanie autora wątku wskazuje na braki w podstawach, ale to nie powód, żeby dawać dziurawe rozwiązanie. Nie trzyma się w bazie oryginałów haseł, bo grozi to wyciekiem tych haseł w przypadku wykradzenia bazy. Można trzymać hasła zaszyfrowane, ale są one względnie łatwe do wyciągnięcia, bo to kwestia jednego ataku brute-force (zgadnięcie jednego hasła od razu odszyfrowuje wszystkie hasła z bazy). Lepsze rozwiązanie - można trzymać hasła zahashowane (czyli "zaszyfrowane" funkcją jednostronną, czyli taką, której działania nie da się odwrócić, np. algorytm MD5 czy SHA), ale jest to podatne na atak z użyciem rainbow table (tablica zawierająca wygenerowane pary hasło-hash dla popularnych haseł, wtedy tylko sprawdza się, czy zapisany w bazie hash znajduje się w ranbow table, to bardzo szybka operacja; jest to zbliżone do ataku słownikowego - dlatego warto mieć nietypowe hasło i wykorzystywać w nim znaki specjalne). Najlepszym zabezpieczeniem jest hash + salt, czyli funkcja jednostronna wyliczająca hash nie samego hasła, a ciągu hasło+salt, przy czym salt jest zapisany w bazie i obowiązkowo różny dla każdego użytkownika. W tym przypadku nie pomoże rainbow table, pozostaje tylko brute force (albo atak słownikowy dla frajerskich haseł w rodzaju password1) i to indywidualnie dla każdego konta.

@autor: Rozumiem, że to co napisałem może brzmieć skomplikowanie, ale jak poczytasz o hashowaniu haseł (np. https://sekurak.pl/kompendium[...]czenstwa-hasel-atak-i-obrona/), to powinno się nieco wyklarować.

0

Dzięki panowie. Temat do zamknięcia

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0