Sprawdzenie hasła w aplikacji konsolowej

0

Hej, napisałem program, który wymaga podania poprawnego hasła, a w przypadku jego braku jest ono ustalane. Gdy podaję hasło zapisane w pliku, to wyskakuje, że jest błędne. Dlaczego tak się dzieje skoro napisy są identyczne?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

void ustawHaslo (FILE *haslo)
{
	char noweHaslo [100];
	
	printf ("Brak ustawionego hasla.\nPodaj haslo: ");
	scanf ("%s", noweHaslo);
	haslo = fopen ("haslo.txt","w");
	fprintf (haslo, "%s", noweHaslo);
	fclose (haslo);
	return;
}

void wprowadzHaslo (void)
{
	FILE *haslo;
	
	if ((haslo = fopen ("haslo.txt","r+")) == NULL) // gdy brak pliku
	{
		ustawHaslo (haslo);
		haslo = fopen ("haslo.txt","r+");
	}
	
	char pierwszyZnak = fgetc (haslo);
	if (pierwszyZnak == EOF) // gdy plik jest pusty
	{
		ustawHaslo (haslo);
		haslo = fopen ("haslo.txt","r+");
	}
	
	else // wprowadzanie hasła i weryfikacja
	{	
		char wprowadzoneHaslo [100];
		char prawdziweHaslo [100];
		fscanf (haslo, "%s", prawdziweHaslo);
		fclose (haslo);
		printf ("Wprowadz haslo: ");
		do
		{
			scanf ("%s", wprowadzoneHaslo);
			if (strcmp (wprowadzoneHaslo, prawdziweHaslo) == 0)
			{
				printf ("Poprawne haslo.\n");
				return;
			}
			else printf ("Bledne haslo! Wprowadz ponownie: ");
		}
		while (1);	
	}
}

int main ()
{
	printf ("\t\tBaza danych.\n\n");
	wprowadzHaslo ();
	
	return 0;
}

1

Jeden chaos.
Kontrolujesz intelektualnie miejsca, w których otwierasz plik ? Czy nigdy się nie zastanawiałeś?

Cięcię na funkcje owszem, to teoretycznie element lepszego projektu, ale tu jest zupełnie przypadkowe

Po drugie:
poczytaj dokumentację, NA PRZYKŁAD co zwraca fgetc () i co to jest EOF

Po trzecie: włacz maksimum ostrzeżeń kompilacji i je czytaj.

Jestem najzupełniej pewien, że to co wyłapałem, to tylko kropla.

2

Pobierasz znak, żeby sprawdzić czy plik jest pusty i ta pierwsza litera hasła przepada. Trzeba oddać ją z powrotem do bufora ungetc, albo inaczej zaimplementować całą tą funkcję.

int pierwszyZnak = fgetc(haslo);
ungetc(pierwszyZnak, haslo);
0

dzięki za wskazówki

3
jvoytech napisał(a):

Pobierasz znak, żeby sprawdzić czy plik jest pusty i ta pierwsza litera hasła przepada. Trzeba oddać ją z powrotem do bufora ungetc, albo inaczej zaimplementować całą tą funkcję.

int pierwszyZnak = fgetc(haslo);
ungetc(pierwszyZnak, haslo);

Straszana rada. On po prostu źle obsługuje błędy wczytywania. Dodanie ungetc to po prostu ignorowanie problemów i dodawanie w przyszłości innych.

Poprawki do oryginału nie przejdą prze moją klawiaturę, bo problemów jest dużo więcej.
Powinno być coś w ten deseń:

#define PASSWORD_FILE_NAME "haslo.txt"

void savePassword(const char *password)
{
   FILE* f = fopen(PASSWORD_FILE_NAME, "w");
   if (!f) {
      perror("write password failed");
      exit(1);
   }
   if (fprintf(f, "%s", password) < 0) {
      perror("write password data failed");
      fclose(f);
      exit(1);
   }
   fclose(f);
}

// returns 0 on failure
int readPassword(char* password)
{
   FILE* f = fopen(PASSWORD_FILE_NAME, "r");
   if (!f) {
      perror("read password failed");
      return 0;
   }
   if (fscanf(f, "%99s", password) != 1) { // assuming: char password[100]
      perror("read password data failed");
      fclose(f);
      return 0;
   }
   fclose(f);
   return 1;
}

https://godbolt.org/z/znh389GoE

0

@kopikopa: Bardzo, ale to bardzo fajnie piszesz.
Pracować z Tobą to będzie przyjemność.

Po pierwsze to tuż przed samym użyciem strcmp(), wyświetl hasło z pliku i to wczytane z klawiatury.

I tak dodajesz te 2 linijki

	        
            printf ("\nwprwadzoneHaslo%c%s%c",34,wprowadzoneHaslo,34);
			printf ("\nwprwadzoneHaslo%c%s%c",34,prawdziweHaslo,34);
			
            if (strcmp (wprowadzoneHaslo, prawdziweHaslo) == 0)...

I przy ustalonym haśle - "haselko" masz taki wynik

Baza danych.

Brak ustawionego hasla.
Podaj haslo: haselko
Wprowadz haslo: haselko

wprwadzoneHaslo"haselko"
wprwadzoneHaslo"aselko"Bledne haslo! Wprowadz ponownie:

Otrzymujesz - "aselko"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

void ustawHaslo (FILE *haslo)
{
	char noweHaslo [100];
	
	printf ("Brak ustawionego hasla.\nPodaj haslo: ");
	scanf ("%s", noweHaslo);
	haslo = fopen ("haslo.txt","w");
	fprintf (haslo, "%s", noweHaslo);
	fclose (haslo);
	return;
}

void wprowadzHaslo (void)
{
	FILE *haslo;
	
	if ((haslo = fopen ("haslo.txt","r+")) == NULL) // gdy brak pliku
	{
		ustawHaslo (haslo);
		haslo = fopen ("haslo.txt","r+");
	}else{
           fclose(haslo);
          }
	
	
	haslo = fopen ("haslo.txt","r+");
		
		char wprowadzoneHaslo [100];
		char prawdziweHaslo [100];
		fscanf (haslo, "%s", prawdziweHaslo);
		fclose (haslo);
		printf ("Wprowadz haslo: ");
		do
		{
			scanf ("%s", wprowadzoneHaslo);
			printf ("\nwprwadzoneHaslo%c%s%c",34,wprowadzoneHaslo,34);
			printf ("\nwprwadzoneHaslo%c%s%c",34,prawdziweHaslo,34);
			if (strcmp (wprowadzoneHaslo, prawdziweHaslo) == 0)
			{
				printf ("Poprawne haslo.\n");
				return;
			}
			else printf ("\nBledne haslo! Wprowadz ponownie: ");
		}
		while (1);	
	
}

int main ()
{
	printf ("\t\tBaza danych.\n\n");
	wprowadzHaslo ();
	
	return 0;
}
0
johnny_Be_good napisał(a):

@kopikopa: Bardzo, ale to bardzo fajnie piszesz.
Pracować z Tobą to będzie przyjemność.

Budujesz @johnny_Be_good krąg wzajemnej adoracji ? Adresuj kadzidła do @zkubinski , bardziej się opłaca

Dajcie znać, gdzie będziecie pracować (abym był maksymalnie daleko)

Podejmując się przeróbek BŁĘDNEGO kodu konserwujesz błędy i złe nawyki

0
ZrobieDobrze napisał(a):
johnny_Be_good napisał(a):

@kopikopa: Bardzo, ale to bardzo fajnie piszesz.
Pracować z Tobą to będzie przyjemność.

Budujesz @johnny_Be_good krąg wzajemnej adoracji ? Adresuj kadzidła do @zkubinski , bardziej się opłaca

Dajcie znać, gdzie będziecie pracować (abym był maksymalnie daleko)

Podejmując się przeróbek BŁĘDNEGO kodu konserwujesz błędy i złe nawyki

@ZrobieDobrze:
Tak, wy od 1980 nie podejmowaliście się niczego, puste półki były. Takie to wasze metody, takie to efekty tych waszych metod.
Siedzieć i czekać aż się samo zrobi albo zawali.
I teraz tego samego chcesz mnie uczyć?

1
kopikopa napisał(a):

Hej, napisałem program, który wymaga podania poprawnego hasła, a w przypadku jego braku jest ono ustalane. Gdy podaję hasło zapisane w pliku, to wyskakuje, że jest błędne. Dlaczego tak się dzieje skoro napisy są identyczne?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

void ustawHaslo (FILE *haslo)
{
	char noweHaslo [100];
	
	printf ("Brak ustawionego hasla.\nPodaj haslo: ");
	scanf ("%s", noweHaslo);
	haslo = fopen ("haslo.txt","w");
	fprintf (haslo, "%s", noweHaslo);
	fclose (haslo);
	return;
}

void wprowadzHaslo (void)
{
	FILE *haslo;
	
	if ((haslo = fopen ("haslo.txt","r+")) == NULL) // gdy brak pliku
	{
		ustawHaslo (haslo);
		haslo = fopen ("haslo.txt","r+");
	}
	
	char pierwszyZnak = fgetc (haslo);
	if (pierwszyZnak == EOF) // gdy plik jest pusty
	{
		ustawHaslo (haslo);
		haslo = fopen ("haslo.txt","r+");
	}
	
	else // wprowadzanie hasła i weryfikacja
	{	
		char wprowadzoneHaslo [100];
		char prawdziweHaslo [100];
		fscanf (haslo, "%s", prawdziweHaslo);
		fclose (haslo);
		printf ("Wprowadz haslo: ");
		do
		{
			scanf ("%s", wprowadzoneHaslo);
			if (strcmp (wprowadzoneHaslo, prawdziweHaslo) == 0)
			{
				printf ("Poprawne haslo.\n");
				return;
			}
			else printf ("Bledne haslo! Wprowadz ponownie: ");
		}
		while (1);	
	}
}

int main ()
{
	printf ("\t\tBaza danych.\n\n");
	wprowadzHaslo ();
	
	return 0;
}

Lista problemów:

  • nazwy symboli po polsku (angielskiego nie da się uniknąć)
  • ustawHaslo składa obietnicę, ze coś zrobi z plikiem (argumentem), a tymczasem argument jest ignorowany i służy jako zmienna lokalna.
  • pomieszanie zapisu z logiką przetwarzania hasła - takie rzeczy się rozdziela
  • brak obsługi błędów, zamiast właśiwej obsługi błędów, jest czytanie znak po znaku - które jest źródłem problemu
  • za długi funkcje
  • brak zabezpieczeń przed buffer overflow
  • hasło nie może zwierać spacji

Jeśli @kopikopa dopiero zaczął(a) się uczyć programowania to jest całkiem nieźle.
Jednak jeszcze jest jest sporo do poprawienia. Kometarze, od johnny_Be_good wskazują, że jego poziom zaawansowania jest nie wiele lepszy.
Ja rozumiem, że johnny_Be_good próbuje pomóc jak potrafi, ale powinien sobie darować próby stawiania innych po kontach i nie powinien się obrażać jeśli ktoś wskazuje, że jego rady nie są prawidłowe.
Fora (itp) są po to, by pomagać sobie na wzajem, wskazywać dobre praktyki.
Sam próbuje czasami udzielać odpowiedzi spoza zakresu moich umiejętności, a jak ktoś wskazuje mi błedy, to uczę się czegoś nowego, a nie wszczynam krucjatę urażonej dumy.

A poniżej jest przekombinowana wersja tego kodu:
https://godbolt.org/z/3aeMEfGfb

Odgadnie ktoś jakie jest ustawione hasło? (disclaimer - to nie jest metoda zgodna ze współczesnymi zasadami bezpieczeństwa, ale lepsze niż otwarty tekst).

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