PHP prijava, odjava i registracija korisnika

Discussion in 'Generalna diskusija' started by Surveyor, Aug 20, 2010.

  1. Surveyor

    Surveyor Novi član

    Predpostavljam da čitalac ima bar osnovno znanje iz HTML-a, PHP-a i MYSQL-a. Zbog same količine programskog koda, neću ići u detalje koji se po mom mišljenju tiču tih osnova.
    Za brzi kurs u navedenom posjetite http://www.w3schools.com
    Instalirajte sljedeći software:
    WAMP server http://www.wampserver.com/en/download.php
    Komodo Edit http://www.activestate.com/komodo-edit/downloads
    (može i neki drugi, uglavnom je potreban MYSQL i PHP server i poželjno je imati PHP editor).
    (Upustvo za instaliranje WAMP servera i kreiranje korisnika potražite na internetu).

    Lijevi klik na ikonicu WAMP servera, i izaberite phpMyAdmin
    [​IMG]

    Napravite novu bazu pod imenom „primjer“.
    [​IMG]

    Napravite novu tabelu u bazi „primjer“ pod imenom „korisnici“ i napišite da ima 7 kolona.
    [​IMG]

    Strukturu tabele postavite kao na slici:
    [​IMG]

    Postavite da polje „id“ bude primary (primarni ključ- kolona u kojoj ne postoje dva polja sa istim vrijednostima).
    (auto_increment- automatski povećava vrijednost polja „id“ za jedan).
    INT- integer (cijeli broj).
    VARCHAR- znakovi (length- maksimalan broj znakova u jednom polju).

    Sada imamo bazu i tabelu.

    Ideja je sljedeća:
    1. Napraviti funkcije (phpfunkcije.php) za:
    konekciju na bazu,
    funkciju koja provjerava da li je korisnik trenutno prijavljen (ako jeste- ispisati link za odjavu korisnika, ako nije- ispisati formu za prijavu korisnika),
    funkciju za sigurnost unesenih podataka,
    funkciju za provjeru prijave (da li su uneseni podaci ekvivalentni onima u bazi).
    2. index.php na kojem ćemo ispisati formular za prijavu, link za registraciju i odjavu.
    3. prijava.php gdje ćemo pozvati funkcije za provjeru prijave i napraviti sesiju ako je prijava validna.
    4. odjava.php gdje ćemo da uništimo sesiju.
    5. registracija.php gdje će budući korisnik da unose svoje podatke (email, password, ime, prezime, grad).
    6. registracijaobradi.php gdje ćemo provjeriti da li su uneseni podaci validni, i gdje ćemo formirati aktivacijski email i poslati korisniku.
    7. registracijaprihvati.php gdje ćemo prihvatiti link iz aktivacijskog email-a i provjeriti njegovu validnost.

    Ispod se nalazi kod za sve navedene stranice sa komentarima. Pošto sam slab sa vremenom, ne mogu da previše idem u detalje, pa ako ima neko pitanja, neka pita ovdje.

    phpfunkcije.php
    Code:
    <?php
        function konekcija_na_bazu($host, $korisnicko_ime, $password, $ime_baze){
            $konekcija = @mysql_connect($host,$korisnicko_ime,$password);
    	mysql_select_db($ime_baze, $konekcija);
      	if(!$konekcija){exit(mysql_error());}
    	if(!mysql_select_db($ime_baze)){exit(mysql_error());}
        }
        function sigurnost($tekst){
    	$tekst=stripslashes($tekst);//paziti na raspored funkcija
    	$tekst=strip_tags($tekst);
    	$tekst=mysql_real_escape_string($tekst);
    	return $tekst;
        }
        function prijava_ispis(){
            if($_SESSION['prijavljen']!='da'){//ako korisnik nije prijavljen, ispisati formu za prijavu
                echo'
                <form method="post" action="prijava.php">
                    <fieldset>	
                        email:<input name="moj_email" type="text" size="6" />
                        password:<input name="moj_password" type="password" size="6" />
                        <input type="submit" value="prijava" />
                        <a href="registracija.php">Registracija</a>
                    </fieldset>
                </form>
                ';
            }
    	else{//ako je korisnik prijavljen, ispisati link za odjavu
                echo'
                <a href="odjava.php">odjava</a> 
                ';
            }
        }  
        function prijava_provjeri($email, $password){
            //zaštita od MySQL injection napada
            $email=sigurnost($email);
            $password=sigurnost($password);
            //provjera podataka u bazi
            $mysql_upit=mysql_query("SELECT * FROM korisnici WHERE email='$email' AND password='$password' AND aktivan='da'");
            $broj_redova=mysql_num_rows($mysql_upit);//broj redova koji su vraćeni kao rezultat upita
            if($broj_redova==1){//ako su ispravni podaci, mora biti samo jedan red
                @session_register('prijavljen');//registruj novu sesiju 
    //(može biti i više varijabli npr. @session_register('prijavljen','ime','prezime'))
                $_SESSION['prijavljen']='da';//varijabla $_SESSION['prijavljen'] je sada dostupna u svim našim php stranicama u kojima smo pozvali funkciju session_start();
                echo 'Uspjesno ste se prijavili.';
            }else{
                echo 'Pogresan email i\ili password.';
            }
            
        }    
    ?> 
    index.php
    Code:
    <?php
        include('phpfunkcije.php');//uključi funkcije iz phpfunkcije.php
        konekcija_na_bazu('localhost', '??????', '??????', 'primjer');//pozovi funkciju konekcija iz phpfunkcije.php
        session_start();//započni sesiju (da bi bilo moguće koristiti $_SESSION[])
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    	<title>Moja stranica</title>
    </head>
    <body>
    <?php prijava_ispis(); ?>
    </body>
    </html>
    prijava.php
    Code:
    <?php
        include('phpfunkcije.php');//uključi funkcije iz phpfunkcije.php
        konekcija_na_bazu('localhost', '??????', '??????', 'primjer');//pozovi funkciju konekcija iz phpfunkcije.php
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    	<title>Prijava</title>
    </head>
    <body>
    <?php
    	if (!isset($_POST['moj_email'])){$_POST['moj_email'] = "";}//u slučaju da vrijednost nije unesena
    	if (!isset($_POST['moj_password'])){$_POST['moj_password'] = "";}//u slučaju da vrijednost nije unesena
    	if($_POST['moj_email']=="" || $_POST['moj_password']==""){//ako email ili (||) password nisu uneseni
    		echo 'Niste unijeli trazene podatke.';
    	}else{
    		prijava_provjeri($_POST['moj_email'], $_POST['moj_password']);
    	}
    ?>
    </body>
    </html>
    Odjava.php
    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    	<title>Odjava</title>
    </head>
    <body>
    <?php
    	session_start();
    	session_destroy();//uništi sesiju
    	echo 'Uspjesno ste se odjavili.';
    ?>
    </body>
    </html>
    registracija.php
    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    	<title>Registracija</title>
    </head>
    <body>
    <form action="registracijaobradi.php" method="post">
    	<fieldset>
    		<b>Unesite podatke:</b><br />
    		email:<input name="email" type="text" size="20" maxlength="40" /><br />
    		password:<input name="password" type="password" size="20" maxlength="20" /><br />
    		ime:<input name="ime" type="text" size="20" maxlength="20" /><br />
    		prezime:<input name="prezime" type="text" size="20" maxlength="20" /><br />
    		grad:<input name="grad" type="text" size="20" maxlength="40" /><br />
    		<input type="submit" value="Registruj" />
    	</fieldset>
    </form> 
    </body>
    </html>
    registracijaobradi.php
    Code:
    <?php
        include('phpfunkcije.php');//uključi funkcije iz phpfunkcije.php
        konekcija_na_bazu('localhost', '??????', '??????', 'primjer');//pozovi funkciju konekcija iz phpfunkcije.php    
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    	<title>Registracija</title>
    </head>
    <body>
    <?php
    	if (!isset($_POST['email'])){$_POST['email'] = "";}//u slučaju da vrijednost nije unesena
    	if (!isset($_POST['password'])){$_POST['password'] = "";}//u slučaju da vrijednost nije unesena	
    	if (!isset($_POST['ime'])){$_POST['ime'] = "";}//u slučaju da vrijednost nije unesena
    	if (!isset($_POST['prezime'])){$_POST['prezime'] = "";}//u slučaju da vrijednost nije unesena
    	if (!isset($_POST['grad'])){$_POST['grad'] = "";}//u slučaju da vrijednost nije unesena
    	//pravimo dodatne varijable, čisto radi lakšeg pisanja
    	$email=sigurnost($_POST['email']);
    	$password=sigurnost($_POST['password']);
    	$ime=sigurnost($_POST['ime']);
    	$prezime=sigurnost($_POST['prezime']);
    	$grad=sigurnost($_POST['grad']);
    	//provjeravamo da li je korisnik već registrovan
    	$mysql_upit=mysql_query("SELECT * FROM korisnici WHERE email='$email'");
            $broj_redova=mysql_num_rows($mysql_upit);
    	
    	if($broj_redova>0){
    		echo 'Vi ste vec registrovani sa ovom email adresom.';
    	}
    	elseif(strlen($email)<10 || strlen($password)<6 || strlen($ime)<2 || strlen($prezime)<2 || strlen($grad)<3){
    		echo 'Nisu uneseni pravilni podaci. Najmanji broj znakova za polja je:<br />
    		email 10 ('.strlen($email).')<br />
    		password 6 ('.strlen($password).')<br />
    		ime 2 ('.strlen($ime).')<br />
    		prezime 2 ('.strlen($prezime).')<br />
    		grad 3 ('.strlen($grad).')';
    	}else{//ako je sve uredu
    		//pravimo aktivacijski email
    		$aktiv_broj =  mt_rand().mt_rand().mt_rand().mt_rand();//slucajni aktivacijski broj
    		$prima = $email;
    		$naslov = "Potvrda registracije na www.??????.com";
    		$tekst = 'Hvala Vam što ste se registrovali. Za aktivaciju Vašeg računa, molimo Vas da kliknete na link: http://www.??????.com/registracijaprihvati.php?aktiv_broj='.$aktiv_broj;
    		if (mail($prima, $naslov, $tekst)) {
      			echo('Poslan Vam je email sa potvrdom o registraciji.<br />
    			Molimo Vas da procitate taj e-mail, i pratite upustvo u njemu, kako bi aktivirali svoj racun.<br />
    			Ukoliko Vasa poruka ne bude u inbox-u, provjerite da li se nalazi u junk ili spam folderu.<br />');
    		} else {
    			echo('Greska prilikom slanja aktivacijskog email-a...');
    		}
    		//upis podataka u bazu
    		mysql_query("INSERT INTO korisnici (email, password, ime, prezime, grad, aktivan)
    			    VALUES ('$email','$password','$ime','$prezime','$grad','$aktiv_broj')");
    	}
    ?>
    </body>
    </html>
    registracijaprihvati.php
    Code:
    <?php
        include('phpfunkcije.php');//uključi funkcije iz phpfunkcije.php
        konekcija_na_bazu('localhost', '??????', '??????', 'primjer');//pozovi funkciju konekcija iz phpfunkcije.php    
    ?>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    	<title>Registracija</title>
    </head>
    <body>
    <?php
    	if (!isset($_GET['aktiv_broj'])){$_GET['aktiv_broj'] = '';}//u slučaju da vrijednost nije unesena
    	$aktiv_broj=sigurnost($_GET['aktiv_broj']);
    	if($aktiv_broj!=''){
    	    mysql_query("UPDATE korisnici SET aktivan='da' WHERE aktivan='$aktiv_broj'");
    	    echo 'Registracija potvrdjena.';
    	}else{
    		echo 'Greska. Pokusajte ponovo.';
    	}
    ?>
    </body>
    </html>
     
  2. selvin

    selvin Moderator

    I ja sam ovo nekad pravio :D Na slican fazon je, bas cu pokusat naci.
     
  3. emir.a

    emir.a Administrator Staff Member

    Par smjernica:

    - Kolona 'aktivan' ne bi trebala biti VARCHAR (265), kada koliko vidim se koriste dvije vrijednosti da ili ne pa shodno tome bi trebala biti ENUM ('da','ne').
    - Ne bi trebalo drzati passwrode u bazi u izvornom obliku, vec iskljucivo kriptovane.
    - Funkcija session_register() je DEPRECATED od 5.3.0
    - U svim upitima se bespotrebno selektuju svi podaci, a dovoljno bi bilo selektovati samo id, a zgodno bi bilo dodati i na kraju LIMIT 1 sve sa ciljem brzine.
     
  4. Surveyor

    Surveyor Novi član

    -VARCHAR (265) sačuvava se i aktivacijski kod, čisto da se ne pravi nova kolona.
    -što se tiče passworda, to je diskutabilno (ako neko ima pristup bazi i passwordima ima pristup svemu, pa nema smisla koristiti dodatnu funkciju), mada nije problem raditi jednosmjerno kodiranje
    -bolje primjer sa, nego bez. Ako mu ne treba, pobriše i radiće i bez nje.
    -Napominjem, ovo je primjer i nema konkretnu namjenu, tako da se ne zna šta treba a šta ne.
     
  5. emir.a

    emir.a Administrator Staff Member

    Ispasce da sitnicram :D

    U prosjeku ce 80% korisnika biti aktivirano, tako da u 80% slucaja cuvas vrijednost od 2 karaktera. Uz to maximlamna duzina je 255.

    većina korisnika koristi istu sifru za vecinu stvari. kriptovanim passwordima se sprijecava kradja i zloupotreba naloga na trecim web stranicama.

    U php6 ce to izazvati prekidanje izvrsenja skripte, pa razmisli da li je bolje sa ili bez.
     
  6. Surveyor

    Surveyor Novi član

    BTW pisao sam 256 u primjeru a ne 265, al' ne bi bilo razlike.

    Za password si upravu :D

    Funkcija se može obrisati i sve će normalno raditi. U novijoj verziji php-a je višak, ali je u starijoj neophodna.

    Što se tiče kolone 'aktivan', zar nije logičnije staviti vrijednosti 'da', 'ne' i aktivacijski broj u jednu kolonu, nego to razdvojiti u dvije kolone gdje bi zauzimalo više resursa?
    Znam da će većinu vremena biti da ili ne, ali onda bi kolona npr. 'aktiv_broj' bila većinom prazna, a zauzimala bi mjesto od 256 karaktera.
     
  7. emir.a

    emir.a Administrator Staff Member

    U principu VARCHAR(255) ne zauzima u svakom slucaju 255 bajta na disku za razliku od CHAR(255). Zato i sadrzi VAR ispred, ali je nesto sporiji od CHAR tipa podataka u slucaju da se pretrazivanje/filtriranje nad tom kolonom.

    U ovom slucaju i ne treba nova kolona, ali nam i kada bolje razmislim ne trebaju ni vrijednosti 'da' i 'ne'. Ako kolona 'aktiv_broj' nije NULL (bolje cuvati NULL nego blank space), tj. sadrzi aktvacijski kod (koji se usto mogao smanjiti na 32 karaktera korsiteći neku od hash funkcija) korisnik nije aktivan, a ako je NULL se je korisnik aktivirao.

    U upitu za provjeru logina bi bilo .... WHERE ... AND aktiv_broj IS NULL za aktivirane korisnike.
     
  8. R1D4

    R1D4 Novi član

    Pomoc. Pls.
    Uradio sam ovo gore sve navedeno i kad ispunim registracijski formular i kliknem za dalje izbaci mi slijedece:
    Warning: mail() [function.mail]: Failed to connect to mailserver at "localhost" port 25, verify your "SMTP" and "smtp_port" setting in php.ini or use ini_set() in E:\wamp\www\registracijaobradi.php on line 43
    Greska prilikom slanja aktivacijskog email-a...

    Sta moram uraditi da ispravim ovo.
     
  9. emir.a

    emir.a Administrator Staff Member

    Nemaš mail server na loklanoj mašini. Ako imas neki hosting, podgini to tamo i trebalo bi da radi.

    Alternativno, trebao bi da instaliras i podesis softver za mail server na svom kompjuteru.
     
  10. R1D4

    R1D4 Novi član

    Kako bi mogao da ubacim jos jedan link na koji bi mogli uci samo registrovani clanovi.
     
  11. emir.a

    emir.a Administrator Staff Member

    Na vrh fajla koji treba 'zaštiti' od neregistrovanih korisnika stavis :

    Code:
    <?php
    if (isset($_SESSION['prijavljen']) and $_SESSION['prijavljen'] == 'da')
    {
    	echo 'Imate pravo pristupa';
    }
    else
    {
    	echo 'Nemate pravo pristupa';
    }
    ?>
    
    ... ili još bolje sa funkcijom

    Code:
    <?php
    
    function is_logged()
    {
    	if (isset($_SESSION['prijavljen']) and $_SESSION['prijavljen'] == 'da')
    	{
    		return true;
    	}
    
            return false;
    }
    ?>
    
    i upotreba funkcije...

    Code:
    <?php
    
    if (!is_logged())
    {
        exit('Nemate pravo pristupa');
    }
    
    ?>
    
    EDIT: Ovo bi trebalo raditi poduslovom da si radio po ovom tutorialu.
     
  12. R1D4

    R1D4 Novi član

    Hvala Majstore.
     
  13. R1D4

    R1D4 Novi član

    Sorry opet ja. Pojavi mi se ovo, imal rjesenja za ovo.
    Notice: Undefined index: prijavljen in C:\wamp\www\phpfunkcije.php on line 15 na index.php
     
  14. emir.a

    emir.a Administrator Staff Member

    Možes ovo dodati na vrh fajla phpfunkcije.php da izbjegneš prikazivanje tog nivoa 'grešaka', tačnije notices.

    Code:
    error_reporting(E_ALL & ~E_NOTICE);
    
    No, ne bih ti to preporučio, nego postaj 15. liniju fajla phpfunkcije.php da vidimo o čemu se tačno radi.
     
  15. R1D4

    R1D4 Novi član

    if($_SESSION['prijavljen']!='da'){//ako korisnik nije prijavljen, ispisati formu za prijavu
     
  16. selvin

    selvin Moderator

    Pa vjerovatno ti je bolje pokusati obrnutom logikom, jer ti mozda pravi problem ako session nije postavljen nikako.
     
  17. Surveyor

    Surveyor Novi član

    Ovako ja eliminišem NOTICE upozorenja:

    Code:
    if (!isset($_SESSION['prijavljen'])){$_SESSION['prijavljen']='ne';}
    Tj. ako $_SESSION['prijavljen'] nema vrijednost, upiši neku default-nu.
     
  18. R1D4

    R1D4 Novi član

    Uradio sam registraciju po ovom turtorijalu i radi, e sad kad hocu da mi samo registrovani clanovi vide link ili nesto drugo uradio sam funkciju.

    Code:
    <?php

    function is_logged()
    {
    if (isset($_SESSION['prijavljen']) and $_SESSION['prijavljen'] == 'da')
    {
    return true;
    }

    return false;
    }
    ?>


    i upotreba funkcije, medjutim kad stavim ovo na vrh fajla imam samo bijelu stranicu

    Code:
    <?php

    if (!is_logged())
    {
    exit('Nemate pravo pristupa');
    }

    ?>
    Pls, Imal Pomoci za ovo.
     
  19. selvin

    selvin Moderator

    Zavisi gdje na vrh fajla. Vjerovatno si zeznuo nesto drugo.

    EDIT: Probaj stavit da ispise nesto i kad si logovan.
     
  20. Surveyor

    Surveyor Novi član

    Nemoj koristiti exit(), probaj ovako:
    Code:
    <?php
    if (!is_logged())
    {
    header('Location:neprijavljen.php');
    }
    ?>
    
    Gdje ti je neprijavljen.php neka stranica gdje ćeš da obavjestiš korisnika da nije prijavljen (stavi to iznad svih html tagova).