Autor Zpráva
Demoniak
Profil
Dobré odpoledne, jdu na Vás s prosbou, napsal jsem si script na trvalé přihlášení, chtěl bych po Vás pouze zkontrolovat, zde se dá použít z bezpečnostního hlediska či jestli obsahuje nějaké chyby.

soubor login_zpracuj.php :
if($p == "on"){
                        
                        function RandNumber($e){
 
 
                        for($i=0;$i<$e;$i++){
                        $rand =  $rand .  rand(0, 9);  
                             }
                         return $rand;

                         }
                         $prihljmeno = $Vysledek['nick'];
                         $prihlid = $Vysledek['id'];
                        $hash = RandNumber(10);
                        $trvale = md5($Vysledek['nick'].$Vysledek['mail'].$Vysledek['heslo']);
                        $trvale_prihlas = "INSERT INTO trvale_prihlaseni (trvale,nick,iduzivatele,hash) VALUES ('$trvale','$prihljmeno','$prihlid','$hash')";
                        $trvale_prihlas = mysql_query($trvale_prihlas) or die(mysql_error());
                        $najdi_prihlaseni = "SELECT * FROM trvale_prihlaseni WHERE";
                        setcookie ("nick", $Vysledek['nick'], time() + 60*60*24*30*12);
                        setcookie ("ssid", $trvale, time() + 60*60*24*30*12);
                        setcookie ("id_prohlizece", $hash, time() + 60*60*24*30*12);
                    };
Zde by mělo docházet k ukládání proměných do Cookies a do DB při prvním přihlášení. Proměnná $p checkbox a uživatel má na výběr jestli chce trvale přihlásit či nikoli.

soubor index.php :
session_start();
if(!isset($_SESSION['prihlasen'])){  //kontrola jestli je uzivatel prihlasen a pokud ne, pokracujeme
$uzivatel = $_COOKIE['nick'];
$ssid = $_COOKIE['ssid'];
$id_prohlizece = $_COOKIE['id_prohlizece'];
if(isset($uzivatel) and isset($ssid) and isset($id_prohlizece)){ //kontrola jestli v Cookies neco je
    require "db.php";
$najdi_prihlaseni = "SELECT * FROM trvale_prihlaseni WHERE nick='$uzivatel' and trvale='$ssid' and hash='$id_prohlizece' LIMIT 1";
$najdi_prihlaseni = mysql_query($najdi_prihlaseni)or die (mysql_error());
$vyber = mysql_fetch_array($najdi_prihlaseni);
if(isset($vyber['iduzivatele'])){ //Pokud to v array neco naslo, pokracujeme
    $iduzivatele = $vyber['iduzivatele'];
    $najdi_uzivatele = "SELECT * FROM uzivatel WHERE id='$iduzivatele' LIMIT 1";
    $najdi_uzivatele = mysql_query($najdi_uzivatele);
    $u = mysql_fetch_array($najdi_uzivatele);
    if(isset($u['nick'])){
     
                    $_SESSION['prihlasen'] = 1;
                    $_SESSION['jmeno'] = $u['jmeno'];
                    $_SESSION['prijmeni'] = $u['prijmeni'];
                    $_SESSION['login'] = $u['nick'];
                    $_SESSION['UserId'] = $u['id'];
                    $_SESSION['UserMail'] = $u['mail'];
                    $_SESSION['Prava'] = $u['prava'];   
        
    }
    
    
}}
}

Moc díky za případné připomínky
YOYO
Profil
Připomínka č.1: srovnej si odsazení, tohleto je silně nečitelné, nediv se, že Ti nikdo neodpověděl,.. nikdo to totiž nechtěl ani číst.

připomínka č.2: udělej si trochu lepší systém v pojmenování proměnných, například $trvale_prihlaseni je napřed query string, pak je to mysql odpověď !?!? .. a co je třeba sloupec "trvale" v db s proč obsahuje hash a ve sloupci hash je nějaké náhodné číslo!?

připomínka č.3: celé mi to přijde hrozně zmatečné ve všech ohledech,.. k čemu třeba potřebuješ id_prohlížeče a co to vlastně je? má to jinej význam, než ssid?

připomínka č.4: nemyslím si, že je potřeba všechny userdata mít uložené v session, když je stejně taháš z db

jinak netvrdím, že to nefunguje, možná jo, možná i bezpečně, ale jak jsem řekl, nikomu se to nebude chtít zjišťovat
Demoniak
Profil
id_prohlizece mám nastavené na náhodné číslo, pro případ, že by se uživatel chtěl trvale přihlásit na více počítačích najednou, omlouvám se, jinak mě to nenapadlo. Nechci do toho zbytečně zatahovat IP adresu :)

je to funkční a pravda, je to pěkně zmatené, psal sem to rychle a bez ohledu na čitelnost, napravím.

v session mám toto všechno uložené proto, protože jinde různé session údaje porovnávám s databází.

Děkuji za zpětnou vazbu.


Případně dodám přehlednost a soubor a odhlášením, pro někoho, kdo by toto hledal. Ovšem později, až budu na svém PC.

EDIT:Tak jsem si s tím trošku pohrál, dal tomu nějaký řád, tak komu se bude chtít testujte a používejte dle libosti :)

nebudu tedy uvádět přihlašovací formulář,který odesílá metodou post data do login_zpracuj.php. Jsou to dva inputy s checkboxem a submit tlačítkem.

soubor login_zpracuj.php

<?php 
ob_start();
/*
* Tetno soubor zjisti zda se takovy uzivatel s takovym heslem v databazi nachazi. 
* Pokud ano, do sessions o tom ulozime informaci.
* A pokud zaškrtl trvalé přihlášení, tak jej trvale přihlásíme.
*/
session_start(); // Budeme pracovat se session, musíme je nastartovat.
if(isset($_POST['nick']))   //pokud byl odeslán formulář, pokračujeme
{
    require 'db.php';
    $nick = $_POST['nick'];
    $heslo = md5($_POST['heslo']);
    $p = $_POST['prihlas'];
        
    $query = MySQL_Query("SELECT * FROM `uzivatel` WHERE `nick` = '$nick' and `heslo` = '$heslo'") or die (mysql_error());
        // Vybereme uživatele se zadaným jménem a heslem
       $Vysledek = mysql_fetch_array($query);
        
        if($Vysledek['nick'] and $Vysledek['aktivace'])
            { // pokud tato proměnná obsahuje data, bylo zadané správné jméno a heslo
                    
                $_SESSION['prihlasen'] = 1;     // Do sessions si uložíme pár informací o přihlášeném
                $_SESSION['jmeno'] = $Vysledek['jmeno'];
                $_SESSION['prijmeni'] = $Vysledek['prijmeni'];
                $_SESSION['login'] = $Vysledek['nick'];
                $_SESSION['UserId'] = $Vysledek['id'];
                $_SESSION['UserMail'] = $Vysledek['mail'];
                $_SESSION['Prava'] = $Vysledek['prava'];
                    
                if($p == "on") //Pokud bylo zaškrtnuto políčko pro automatické přihlášení
                    {
                        
                        function RandNumber($e) //funkce pro generování náhodného čísla 
                            {
 
                                for($i=0;$i<$e;$i++)
                                    {
                                        $rand =  $rand .  rand(0, 9);  
                                    }
                                
                                return $rand;

                            }
                              
                        $prihljmeno = $Vysledek['nick'];
                        $prihlid = $Vysledek['id'];
                        $id_prohlizece = RandNumber(10);//Vygenerujeme náhodné číslo, které poslouží jako spojení mezi databází a konkrétním prohlížečem
                        $trvale = md5($Vysledek['nick'].$Vysledek['mail'].$Vysledek['heslo']);//zahashujeme identifikátor uživatele
                        $trvale_prihlas = "INSERT INTO trvale_prihlaseni (trvale,nick,iduzivatele,hash) VALUES ('$trvale','$prihljmeno','$prihlid','$id_prohlizece')";
                            //Vložíme údaje do databáze
                            $vloz_do_db = mysql_query($trvale_prihlas) or die(mysql_error());
                        setcookie ("nick", $Vysledek['nick'], time() + 60*60*24*30*12); //nastavíme cookies podle hodnot které se nám uložily do databáze
                        setcookie ("ssid", $trvale, time() + 60*60*24*30*12);
                        setcookie ("id_prohlizece", $hash, time() + 60*60*24*30*12);
                    };
                  $bl="index.php?h=1"; // přesměrujeme na index s hláškou o úspěšném přihlášení
            }else
                {
                    $bl="index.php?h=2"; //chyba ve jmenu nebo heslu
                }     


    mysql_free_result($query);
}else
    {        
        echo "Zde nic není;-)";
    }
header("location: $bl");//vykonáme přesměrování na index
ob_end_flush();
?>
Hlášky mám uvedené v poli v souboru hlasky.php (index.php?h=1 nebo ?h=2) a vypisuju je na stránce index.php pomocí javascriptu. Pokud bude zájem tak to zde zveřejním.

úprava souboru index.php
<?php
/* na začátek souboru index.php vložíme kontrolu pokud je uživatel již přihlášen,
* pokud ano tak trvalé přihlášení přeskočíme
* pokud není tak zkontrolujeme zda si vůbec přeje být automaticky přihlášen
* a pokud si to nepřeje tak trvalé přihlášení opět přeskočíme */

session_start(); // startujeme session.
if(!isset($_SESSION['prihlasen'])) //Pokud uživatel není přihlášen, pokračujeme
    {
        $uzivatel = $_COOKIE['nick'];
        $ssid = $_COOKIE['ssid'];
        $id_prohlizece = $_COOKIE['id_prohlizece'];
        
        if(isset($uzivatel) and isset($ssid) and isset($id_prohlizece)) //Zkontrolujeme cookies a pokud obsahují hodnoty, pokračujeme
            { 
                require "db.php";
                $najdi_prihlaseni = "SELECT * FROM trvale_prihlaseni WHERE nick='$uzivatel' and trvale='$ssid' and hash='$id_prohlizece' LIMIT 1";
                    //Vybereme uživatele z databáze, který je uložen v cookies
                $zkontroluj_udaje = mysql_query($najdi_prihlaseni)or die (mysql_error());
                    $vyber = mysql_fetch_array($zkontroluj_udaje);
                        
                        if(isset($vyber['iduzivatele'])) //Pokud uživatel existuje pokračujeme v přihlášení
                            {
                                $iduzivatele = $vyber['iduzivatele'];
                                $najdi_uzivatele = "SELECT * FROM uzivatel WHERE id='$iduzivatele' LIMIT 1";
                                    $zkontroluj_uzivatele = mysql_query($najdi_uzivatele);//Sáhneme si do databáze s uživateli pro jeho data
                                        $u = mysql_fetch_array($zkontroluj_uzivatele);
    
                                            if(isset($u['nick'])) //Pokud existují načteme je do session
                                                {
     
                                                    $_SESSION['prihlasen'] = 1;
                                                    $_SESSION['jmeno'] = $u['jmeno'];
                                                    $_SESSION['prijmeni'] = $u['prijmeni'];
                                                    $_SESSION['login'] = $u['nick'];
                                                    $_SESSION['UserId'] = $u['id'];
                                                    $_SESSION['UserMail'] = $u['mail'];
                                                    $_SESSION['Prava'] = $u['prava'];   
        
                                                }
    
    
                            }
            }
    }
?>

Nakonec taky musíme dát uživateli možnost se odhlásit. Čili přes odkaz <a href="logout.php?logout=yes">Odhlásit se</a>

soubor logout.php

<?php   
ob_start();
if(isset($_GET['logout']) and $_GET['logout']=="yes") //na odhlašení odkazuji logout.php?logout=yes , proto pokud toto platí, pokračujeme v odhlášení
    { 
        Session_Start(); //nastartujeme session
        Session_Destroy(); // a ihned je smažeme
        
        $id_prohlizece = $_COOKIE['id_prohlizece'];
  
        if(isset($_COOKIE['id_prohlizece'])) //Pokud existují cookies pro automatické přihlášení tak je za chvilku smažeme
            {
                require "db.php";
                $vymaz_zdb = "DELETE FROM trvale_prihlaseni WHERE hash='$id_prohlizece'";
                    $vymaz_prihlaseni = mysql_query ($vymaz_zdb)or die(mysql_error());//zde vymažeme z databáze údaje o trvalém přihlášení v tomto prohlížeči
                    
                    setcookie("ssid");setcookie("id_prohlizece");setcookie("nick");//Smažeme přihlašovací data z cookies
            }
        $bl="index.php?h=3"; //vložíme do proměnné přesměrování na index.php
    }
ob_end_flush();
header("location: $bl");//a nakonec přesměrujeme
?>

Dodatečný odkaz na živou prezentaci http://servisnikniha.comehere.cz (přihlašovací jmého "test" a heslo "test")

Prosím dodatečné připomínky. Díky
YOYO
Profil
Máš zvláštní styl odsazování, takové dvojité...
A asi jsem hodně puntičkář, ale některé proměnné máš stále pojmenované dost nelogicky a nedodržuješ v tom moc řád, mícháš angličtinu s češtinou, někde začínáš s velkým písmenem, někde s malým, někde máš podtržítkovou_notaci někde camelCase, no dejme tomu,.. ale že pojmenováváš jinak sloupce v databázi, jinak pak proměnné s těma vytahanejma datama a jinak pak když to uložíš do sessions, v tom se přece ani sám nemůžeš vyznat.

1.) rozhodně bych kontroloval, zda byly odeslány všechny formulářové pole s kterými pak pracuješ (isset může mít víc parametrů):
if(isset($_POST['nick'], $_POST['heslo'], $_POST['prihlas']))

edit:
1 a půl.) (asi nejreálnější bezpečnostní chyba a já ji hned přehlíd) rozhodně ošetřuj všechna POST data, která pak šoupeš do query dotazů pomocí
mysql_real_escape_string()

2.) tvá fce RandNumber vrací řetězec, to je dost zavádějící název,..

3.) jako spojení mezi databází a konkrétním prohlížečem přeci slouží sssid

4.) vážně potřebuješ mít nick uložen i v cookies?

5.) vážně potřebuješ do tabulky trvale_prihlaseni ukládat data, co už máš v jiné?

6.) jako identifikátor uživatele slouží snad userid, ne? .. proč ten tvůj další identifikátor je v proměnné "$trvale" ? jo aha, to je tvoje vlastní ssid.. normální phpsessid ti nevyhovuje?

nebylo by lepší smazat půlku tvého kodu a místoto toho jen použít
if($p==="on") //zaškrtl trvale přihlášení
    setcookie("PHPSESSID", time() + 60*60*24*30*1)
protože to je přece jediné v čem by se mělo trvalé přihlášení lišit od netrvalého, že se nesmažou cookies po zavření prohlížeče, ne?
Demoniak
Profil
jasně, že by to teoreticky stačilo, ale co když uživatel neaktualizuje přes 20 minut stránku? na straně serveru se vymaže a po aktualizaci stránky se vytvoří nové phpsessid ne?
YOYO
Profil
to máš vlastně pravdu (tedy nejsem si jist, zda se samo změní phpsessid a nepoužije se znova to staré), je potřeba to někam uložit, nejspíš do databáze (ikdyž by to šlo i nějak zašifrovat do cookies) ale rozhodně to lze udělat jednodušeji, než to máš ty, viz http://php.vrana.cz/trvale-prihlaseni.php
panther
Profil
YOYO:
1.) rozhodně bych kontroloval, zda byly odeslány všechny formulářové pole s kterými pak pracuješ
existuje-li jedno odeslane pole, existuji i dalsi, jsou-li odeslany jednim formularem a nejedna-li se o checkboxy. Zbytecne.

rozhodně ošetřuj všechna POST data
nejen POST, vsechna data, ktera jdou do dotazu od uzivatele.
Demoniak
Profil
panther:
nejen POST, vsechna data, ktera jdou do dotazu od uzivatele.
Pochopil jsem správně, že mám ošetřovat jak vstup pro přihlášení, tak i vkládání příspěvků přes <textarea> do DB a včetně jeho následného selectování z DB?
jenikkozak
Profil
Demoniak:
Přesně. Na escapování se bude hodit si přečíst článek Escapování - definitivní příručka.
Demoniak
Profil
jenikkozak, panther, YOYO:
Děkuji, celé stránky opraveny.
panther
Profil
Demoniak:
včetně jeho následného selectování z DB?
pokud jsou data, ktera selectujes, ovlivnitelna uzivatelem, pak je nutno je take escapovat.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: