Profile użytkowników

Sebek

Witam w kolejnym artykule z serii - dla leniwych początkujących. Tym razem napisze jak stworzyć moduł, bo to będzie tylko dodatek, dzięki któremu nasz program bedzie mogło używać wiele osób. Potem możesz dodać opcje personizacji ustawień osobno dla każdego użytkownika. Piszę ten artykuł, przy okazji, gdyż potrzebowałem go do mojego programu. Nie przeciągajmy tego wstępu i jedziemy z koksem.

Pierwsze co to jeśli dodajesz ten moduł do programu który masz juz gotowy, to forme pierwsza pozostawiasz bez zmian no, może kilka małych. Jedyne co musisz zmienić, a właściwie dodać to kilka linijek kodu i dwa komponenty. Żeby mieć już spokuj od razu wrzucimy wszystkie procedurki i zostawimy w spokoju forme 1. Jedyne komponenty jakie musisz wrzucić na forme do dwa Labele. U mnie nazywają się Label2 i Label3. Cation Label2 możnesz zmienić na coś w stylu: "jestes zalogowany jako:" i obok wrzuć Label3, jego caption bezwzględnie (jeśli nie chce Ci się grzebać w kodzie :P) musisz ustawić na "nikt". Teraz przechodzimy do kodu. Do Form1.OnCreate dodaj taki kod:

 Form2:=TForm2.Create(nil);//pokażmy okno logowania
 Form2.ShowModal;//pokażmmy okno logowania

Dzięki niemu na starcie programu pokaże się forma2 na której znajduje się praktycznie cały "moduł" do obługi profilii. Teraz w procedurze OnShow pierwszej formy wstawiamy następujący kodzik:

if Label3.Caption='nikt' then Application.Terminate;

Zaraz po zamknięciu Formy2 na której mamy nasz modulik, pokaże się form1, czyli wystąpi procedura OnShow i wtedy jeśli ktoś się nie zalogował tylko zamknął okno X to caption Labela3 zostaje "nikt", i jeśli program to wykryje - zamknie się. Kod całej form1 bedzie wyglądał tak:

//unit1
{Profile Demo - ©2003 by Sebek - FreeWare
Możesz wykorzystać ten moduł w swoim programie, bez żadnych
ograniczeń - chesz możesz coś o mnie wspomnieć - nie chcesz?
TO NIE :) nie obraże się.

www.4programmers.net
www.sandstorm.tk

Powered by Borland Delphi 6 Enterprise

[email protected]}
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);
begin
 Form2:=TForm2.Create(nil);//pokażmy okno logowania
 Form2.ShowModal;//pokażmmy okno logowania
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Application.Terminate;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
if Label3.Caption='nikt' then Application.Terminate;
{jeśli ktoś spróbuje zamknąćokno logowania bez zalogowania
(czyli kliknie w X) to caption label3 zostanie 'nikt'
wtedy program wykryje to i zamknie się :)}
end;

end.

Form2

Teraz przechodzimy do Drugiej formy na której mamy cały moduł logowania i rejestracji. Pierwszą czynnością jaką powinieneś wykonać to dodanie do uses INIFiles oraz ShlObj. Teraz zabieramy się za kod. Zaraz za {$R *.dfm} wstaw tą funkcję:

function GetP(Folder: Integer): String; // funkcja odczytuje ważniejsze foldery systemowe (tzn. ścieżki do nich :) ) w tym ten do którego zapiszemy nasz plik profile.ini
var FilePath: array[0..MAX_PATH] of char;
begin
  SHGetSpecialFolderPath(0, FilePath, Folder , False);
  Result:=FilePath;
end;

Dzięki tej funkcji odczytamy ścieżkę do folderu Moje dokumeny, oczywiście nic nie stoi na przeszkodzie, żebyś gdzie indziej zapisał plik z loginami i hasłami, na końcu potem kody na inne systemowe foldery(dzięki Mirek ;) ). Teraz wstawiamy na formę 5 editów (jak mogą być ustawione możesz zobaczyć w kodach źródłowych, powinien być kod tego programiku). Nazwy editów u mnie to Edit od 1 do 5, czyli standardzik. Do tego dodajemy dwa buttony, nazwy nie grają roli. Może spróbuję to schematycznie narysować:

Edit1 Edit3
Edit2 Edit4
Edit5
Button1 Button2

Edit1, Edit2 i Button1 posłużą nam do logowania, natomiast pozostałe 4 komponenty do rejestracji nowego użytkownika. Na koniec dodajemy Listbox, który u mnie przyjmuje nazwę ListBox1. Teraz będą odwołania do zmiennej INI dlatego dodajemy do sekcji var w górnej części naszego kodu taką linijkę: INI: TINIFile;. Teraz dodamy kod w procedurze OnClick ListBoxa. Kod wygląda tak:

INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
Edit1.Text:= INI.ReadString(ListBox1.Items[ListBox1.ItemIndex], 'login','błąd w budowie pliku ini');

Wytłumaczyć można to następująco: po kliknięciu na odpowiedni item w lisbox do edit1 wczytuje się klucz z loginem. Idziemy dalej, może trochę nie pokolei wyszło ale ok. Teraz do procedury OnCreate naszej formy wstaw kod wczytujący wszystkie sekcje z pliku profile.ini. Wygląda on tak:

  INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
  try
    INI.ReadSections(ListBox1.Items);
  finally
    INI.Free;
end;

Teraz dodamy w procedurze OnClick kod który nas zaloguje lub zakończy działanie aplikacji jeśli podamy błędne dane. Oto on:

if
Edit2.Text = INI.ReadString(Edit1.Text, 'haslo','')
then
begin
Form1.Label3.Caption:= Edit1.Text;
Form2.Close;
Form1.Visible:= True
end
else
Application.Terminate;

Wytłumaczę to tak, jeśli hasło, które wpisaliśmy do edit2 jest takie samo jak to w pliku profile.ini to ustaw na pierwszej formie label3.caption na nazwe użytkownika (bedzie pisało zalogowany jako xxx), następnie zamknij okno logowania i pokaż, formę pierwszą. Natomiast jeśli coś pójdzie nie tak aplikacja zamknie się. Teraz dodamy kod dzięki, któremu stworzymy nowego użytkownika. Dodajemy go w procedurze OnClick Buttona numer2.

INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
if
Edit4.Text=Edit5.Text//sprawdzmy czy hasła są takie same
then
begin
INI.WriteString(Edit3.Text, 'login',Edit3.Text);//zapisujemy login
INI.WriteString(Edit3.Text, 'haslo',Edit4.Text);//teraz hasło
INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
INI.ReadSections(ListBox1.Items);//no i teraz odczytujemy drugi raz wszystkie sekcje żeby nowy użytkownik mógł się zalogować bez restartu programu
INI.Free;// :))) szkoda pamieci
Edit3.Text:='';//czyścimy pola rejestracyjne
Edit4.Text:='';//to też
Edit5.Text:='';//i znowu :)
end
else
Application.MessageBox('Hasła są różne od siebie.','Profile Demo', MB_OK+MB_ICONERROR); //jeśli hasła są inne pokaż tylko komunikat

Najpierw program sprawdzi czy pola hasło i wpisz ponownie hasło, mają taką samą zawartość. Jeśli tak będzie to zapisze hasło i login w pliku ini. Następnie od nowa wczyta wszystkie sekcje z pliku ini aby nowy użytkownik mógł się zalogować. Potem czyścimy pola rejestracji. Jeśli natomiast hasła nie będą się zgadzały to program wyświetli stosowny komunikat. Cały kod drugiej formy:

//unit2
{Profile Demo - ©2003 by Sebek - FreeWare
Możesz wykorzystać ten moduł w swoim programie, bez żadnych
ograniczeń - chesz możesz coś o mnie wspomnieć - nie chcesz?
TO NIE :) nie obraże się.

www.4programmers.net
www.sandstorm.tk

Powered by Borland Delphi 6 Enterprise

[email protected]}

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, INIFiles, ShlObj;

type
  TForm2 = class(TForm)
    ListBox1: TListBox;
    GroupBox1: TGroupBox;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Button4: TButton;
    GroupBox2: TGroupBox;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    Button1: TButton;
    Button3: TButton;
    Label6: TLabel;
    Label7: TLabel;
    procedure Button3Click(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;
  INI: TINIFile;

implementation

uses Unit1;

{$R *.dfm}

function GetP(Folder: Integer): String; // funkcja odczytuje ważniejsze foldery systemowe (tzn. ścieżki do nich :) ) w tym ten do którego zapiszemy nasz plik profile.ini
var FilePath: array[0..MAX_PATH] of char;
begin
  SHGetSpecialFolderPath(0, FilePath, Folder , False);
  Result:=FilePath;
end;

procedure TForm2.Button3Click(Sender: TObject);
begin
Application.Terminate;//finish him
end;

procedure TForm2.ListBox1Click(Sender: TObject);
begin
INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
Edit1.Text:= INI.ReadString(ListBox1.Items[ListBox1.ItemIndex], 'login','błąd w budowie pliku ini'); // po kliknięciu na odpowiedni item w lisbox do editu wczytuje się klucz z loginem
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
  try
    INI.ReadSections(ListBox1.Items);//wczytuje wszystkie sekcje z pliku profile.ini
  finally
    INI.Free; //szkoda pamięci :P
end;

end;

procedure TForm2.Button1Click(Sender: TObject);
begin
if
Edit2.Text = INI.ReadString(Edit1.Text, 'haslo','') //jeśli hasło, które wpisaliśmy do edit jest takie samo jak to w pliku profile.ini to ...
then
begin
Form1.Label3.Caption:= Edit1.Text; //ustaw na 1 formie label3.caption na nazwe użytkownika (bedzie pisało zalogowany jako xxx)
Form2.Close;//zamknij okno logowania
Form1.Visible:= True //pokaż form1
end
else //lub jeśli hasło z profile.ini jest inne niz to w edit2 wtedy ...
Application.Terminate; // ...nie ma aplikacji - zostaje zamknięta
end;

procedure TForm2.Button4Click(Sender: TObject);//button od rejestracji nowego usera
begin
INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
if
Edit4.Text=Edit5.Text//sprawdzmy czy hasła są takie same
then
begin
INI.WriteString(Edit3.Text, 'login',Edit3.Text);//zapisujemy login
INI.WriteString(Edit3.Text, 'haslo',Edit4.Text);//teraz hasło
INI := TINIFile.Create(getp(CSIDL_PERSONAL)+'profiletk3.ini');
INI.ReadSections(ListBox1.Items);//no i teraz odczytujemy drugi raz wszystkie sekcje żeby nowy użytkonik mógł się zalogować bez restartu programu
INI.Free;// :))) szkoda pamieci
Edit3.Text:='';//czyścimy pola rejestracyjne
Edit4.Text:='';//to też
Edit5.Text:='';//i znowu :)
end
else
Application.MessageBox('Hasła są różne od siebie.','Profile Demo', MB_OK+MB_ICONERROR); //jeśli hasła są inne pokaż tylko komunikat
end;

end.//und das ist alles

No i to wszystko, życzę miłej pracy przy usprawnianiu modułu, proszę o komentrze, tylko uzasadnione, bo jeśli bedzie to komentarz typu "błe" jak ostatnio Drajwer napisał, to go nie wezme do serca, bo uważam to za przejaw zarozumiałości. Pozdrawiam - Sebek.


Dodatek pierwszy różne katalogi systemowe i ścieżki do nich.

Dzięki tej funkcji możemy odczytać katalogi systemowe:

function GetP(Folder: Integer): String; 
var FilePath: array[0..MAX_PATH] of char; 
begin 
  SHGetSpecialFolderPath(0, FilePath, Folder , False); 
  Result:=FilePath; 
end; 

A katalogi są następujące:

AutoStart getp(CSIDL_STARTUP)
Dane aplikacji getp(CSIDL_APPDATA)
Koszgetp(CSIDL_BITBUCKET)
Ikony dla Panelu Sterowania getp(CSIDL_CONTROLS)
Cookies (Internet) getp(CSIDL_COOKIES)
Wirtualny pulpit getp(CSIDL_DESKTOP)
Fizyczny pulpit getp(CSIDL_DESKTOPDIRECTORY)
Mój komputer getp(CSIDL_DRIVES)
Ulubione getp(CSIDL_FAVORITES)
Czcionki getp(CSIDL_FONTS)
Historia (Internet) getp(CSIDL_HISTORY)
Wirtualny internet getp(CSIDL_INTERNET)
Tymczasowy internet getp(CSIDL_INTERNET_CACHE)
Otoczenie sieciowe getp(CSIDL_NETHOOD)
Dokumenty getp(CSIDL_PERSONAL)
Drukarki getp(CSIDL_PRINTERS)
Programy Menu Start getp(CSIDL_PROGRAMS)
Ostanio używane dokumenty getp(CSIDL_RECENT)
Wyślij do... getp(CSIDL_SENDTO)
Opcje Menu Start getp(CSIDL_STARTMENU)
Wzorce dokumentów getp(CSIDL_TEMPLATES)

Kod podał kiedyś MirekPil na forum. Aha i do uses dodaj - ShlObj. To tyle, pozdrawiam - Sebek.

Koniec dodatku pierwszego, ostatniego.


6 komentarzy

a gdzie jest ta tabela users

Jak łatwo wejść bez hasła. Wystarczy wybrać z listy wcześniej zarestrowanego uzytkownika i dopisać jakąkolwiek litere i wcisnac dalej. Loguje do programu bez hasla.

Hem... Muszę stwierdzić że to jest zabawa a nie profile. Są luki w zabezpieczeniach, a poza tym hasła są przechowywane (nie zaszyfrowane) w plikach INI, mógłbyś przynajmniej zastosować jakiś algorytm szyfrowania jak w Gadu Gadu. Proponuje wejść na: Zabezpieczenie prgramu przed kopiowaniem i skopiować ten algorytm lub na: Bezpieczne szyfrowanie pliku, jeśli chcesz zaszyfrować cały plik z hasłami, odszyfrować; pobrać hasła; zaszyfrować. Zawsze to będzie jakieś zabezpieczenie.

A jak zrobić żeby skasować konto użytkownika??

U mnie to samo jest !! oco chodzi!!

Mam pewien problem. Otóż zrobiłę jak mówisz i np. tworze new usera i potem wpisuje login i haslo ale nic sie nadal nie dzieje. Ani sie nie wlacza glowny program ani nie wylancza. Co jest?