ugrás a tartalomhoz

Ob_start() használata

Freddy88 · 2011. Nov. 15. (K), 14.08
Sziasztok!

Azt szeretném megtudni, hogyan kell helyesen használni az ob_start(); ob_end_flush(); függvényt? Az átirányítást szeretném, hogy működjön!
<?php

$kuld=$_POST['kuld'];
$name=$_POST['name'];
$pass=md5($_POST['pass']);

if(isset($kuld) and isset($pass) and isset($name)){
  $result=mysql_query("SELECT * FROM user WHERE name='$name' and pass='$pass'") or die (mysql_error());
  if(mysql_num_rows($result)==1){
    while($row=mysql_fetch_array($result)){
      $acti=$row['acti'];
      $name=$row['name'];
      $admin=$row['admin'];
    }
    if($acti==2){
    $_SESSION['admin']=$admin;
    $_SESSION['name']=$name;
   
header("Location: $_SERVER[PHP_SELF]");
    }else{ ?><script language="javascript">alert("Nincs aktiválva a regisztrációd");</script><?php }
  }else{ ?><script language="javascript">alert("Hibás felhasználónév és/vagy jelszó");</script><?php }
}else{

?>

<form method="post">

    Felhasználónév:<br /><input type="text" name="name" /><br />Jelszó:<br /><input type="password" name="pass" /><br /><input type="submit" value="Belépek" name="kuld" />

</form>

<?php

}

?>
 
1

Miért?

Poetro · 2011. Nov. 15. (K), 14.44
Egyáltalán nincs szükséged ob_start-ra. Egyszerűen exit-elj az átirányítás után.
3

Hiba

Freddy88 · 2011. Nov. 15. (K), 15.17
Kiegészítettem, beletettem az exit(); függvényt és
[quote]Warning: Cannot modify header information - headers already sent by (output started at /main.php:19) in /include/login.php on line 19
ezt adta vissza.
<?php

$kuld=$_POST['kuld'];
$name=$_POST['name'];
$pass=md5($_POST['pass']);

if(isset($kuld) and isset($pass) and isset($name)){
  $result=mysql_query("SELECT * FROM user WHERE name='$name' and pass='$pass'") or die (mysql_error());
  if(mysql_num_rows($result)==1){
    while($row=mysql_fetch_array($result)){
      $acti=$row['acti'];
      $name=$row['name'];
      $admin=$row['admin'];
    }
    if($acti==2){
    $_SESSION['admin']=$admin;
    $_SESSION['name']=$name;
   
header("Location: $_SERVER[PHP_SELF]");
exit();
    }else{ ?><script language="javascript">alert("Nincs aktiválva a regisztrációd");</script><?php }
  }else{ ?><script language="javascript">alert("Hibás felhasználónév és/vagy jelszó");</script><?php }
}else{

?>

<form method="post">

    Felhasználónév:<br /><input type="text" name="name" /><br />Jelszó:<br /><input type="password" name="pass" /><br /><input type="submit" value="Belépek" name="kuld" />

</form>

<?php

}

?>
4

nem mondtad

Poetro · 2011. Nov. 15. (K), 15.29
Azt nem mondtad, hogy nem ez az egyetlen fájl, amit használsz. Amennyiben másik fájlban már van kimenet, akkor ott a kimenet előtt kell egy ob_start(), majd a végén, amikor már tényleg ki akarsz írni valamit, akkor ob_end_flush().

Ezen kívül érdemes lenne átírni az adatbázis lekérdezésedet, mert most nagyon veszélyes SQL Injection tekintetében. Akkor is illik a felhasználónak kiírni a hibát, ha nincs nála bekapcsolva a JavaScript. Valamint jobb lenne, ha nem használnál ilyet, hogy "Location: $_SERVER[PHP_SELF]", helyette legalább "Location: " . $_SERVER['PHP_SELF']. Ha ezeket kijavítod, talán Crystal is jobban tud majd aludni.
6

Hát lehet...

Freddy88 · 2011. Nov. 15. (K), 15.49
Hát lehet, hogy ezek alap kérdések, meg minden, de nem ezt csinálom, már évek óta, csakpár hónapja.
7

Kicsit belejavítva, átrendezve

mapdesign18 · 2011. Nov. 15. (K), 18.04
Mivel írtad, hogy pár hónapja csinálod ezért szeretnék neked picit segíteni. Mivel a fórumozók írták, hogy elég nagy hiba van a MySQL query terén (amit én is látok), de nem nagyon mondták mi a teendő, ezért a kódodba belejavítottam és picivel biztonságosabbá tettem. Remélem nem bánod.

Egy alap függvényt használtam az SQL injection kivédésére, ami a mysql_real_escape_string(). Ez részben azt csinálja, hogy az összes olyan "veszélyes" karaktert kiszűri, amivel kilehet lépni a MySQL lekérésből.

Például:
SELECT * FROM xy WHERE user='$USER'

Ha az $USER értéke ez lenne:
$USER = "'; DROP TABLE `xy`; next command; next command; ...";


A drop table meg ügye az "xy" adatbázist kompletten letörölné :).

Na íme a változtatott kód:

<?php
// Adatok feldolgozasa
if (isset($_POST['kuld'])) {
   $name = $_POST['name'];
   $pass = $_POST['pass'];

   // Adatok alapszintu ellenorzese
   if (empty($name) and empty($pass)) {
      $error = "A felhasználónév vagy jelszó nem lett megadva.";
   } else {
      // Jelszo ellenorzese (+sql inject kivedese)
      $name = mysql_real_escape_string($name);
      $pass = mysql_real_escape_string(md5($pass));

      $sql = "SELECT * FROM `user` WHERE `name`='$name' AND `pass`='$pass' LIMIT 1";
      $result = mysql_query($sql) or die (mysql_error());

      if (mysql_num_rows($result) == 1) {
         $row = mysql_fetch_array($result);
         $acti = $row['acti'];
         $name = $row['name'];
         $admin = $row['admin'];

         // Aktivalva van?
         if ($acti == 2) {
            $_SESSION['admin'] = $admin;
            $_SESSION['name'] = $name;

            // Atiranyitas
            header("Location: " . $_SERVER['PHP_SELF']);
            exit;
         } else {
            $error = "Nincs aktiválva a regisztrációd";
         }
      } else {
         $error = "Hibás felhasználónév és/vagy jelszó";
      }
   }
}
?>
<form action="" method="post">      
   <?php
   if ($error) {
      // ha van javascript
      $output = '<script language="JavaScript>">';
      $output.= '  window.alert(\'' . $error . '\');';
      $output.= '</script>';
      // ha nincs javascript
      $output.= '<noscript>';
      $output.= '  <span style="color:red;">' . $error . '</span>';
      $output.= '</noscript>';
      echo $output;
   }
   ?> 
   Felhasználónév:<br />
   <input type="text" name="name" /><br />
   Jelszó:<br />
   <input type="password" name="pass" /><br />
   <input type="submit" value="Belépek" name="kuld" />  
</form>
Anno én is az ob_start()-ot és az ob_end_flush()-t használtam, hogy ne dobjon error-t a header() függvény, akkor ha html output kerül felé. Javaslom, hogy előbb a PHP kód fusson, aztán legyen html output, mint a fenti kódban. Így gyakorlatilag az ob_start()-os történet szükségtelenné válik.

A biztonságot persze még számtalan módszerrel lehet csiszolni:
- túl sok hibás belépés után kitiltás
- captcha megkövetelése a belépéshez (x hibás belépés után)
- stb..stb..stb..

PS:
Valamiért a kód színező az alábbi eredményt adta, hol nem is ezt írtam:
08. if (emptyempty($name) and emptyempty($pass)) {

Tehát a helyes:
08. if (empty($name) and empty($pass)) {


Remélem tudtam segíteni. :-)

Üdv,
Bence
9

Nem tökéletes kód amit írtam,

mapdesign18 · 2011. Nov. 15. (K), 18.22
Nem tökéletes kód amit írtam, de talán nem is ez volt a cél. Csak egy kis javítás, esetleg útirány. Minden esetre jobb a kód biztonsági szempontból, mint előtte. Bár, ha van valakinek jobb ötletet a kód összetételére, akkor azt én is kíváncsian várom. :)

PS: Szerintem egy jól megírt MySQL wrapper jobb választás volna.

Például:
http://www.ricocheting.com/code/php/mysql-database-class-wrapper
10

Ne terjesszünk hülyeséget!

janoszen · 2011. Nov. 15. (K), 21.40
Basszus kulcs, ne dezinformáljunk már! A nevezett cikk rohadtul nem mysql_real_escape_string bypass, az ugyanis úgy működik ahogy kell, csak a szerző cseszett köré tenni macskakörmöket, mert akkor szépen működne és még el is adja a saját hülyeségét security holenak.

A nevezett függvény helyes használata az, ha mysql_set_charset függvénnyel megmondjuk a PHP-s MySQL libnek a karakterkódolást, majd macskakörmök között beadjuk a mysql_real_escape_string-elt információt. Értem én, hogy rá vagyunk pattanvan a PDO-ra, de ne higyjük már, hogy az a szent grál és minden más szar.
11

re

Greg · 2011. Nov. 16. (Sze), 09.42
Rengeteg kodot lattam mar, ahol mivel integer ertekrol van szo, mellozik az idezojeleket ilyen esetben, ezert a kod serulekeny.
En egyaltalan nem vagyok rapattanva a PDO-ra, szent gralnak sem tartom, de szerintem a nativ mysql library-nal jobb.
12

mysqli_prepare(). problem

deejayy · 2011. Nov. 16. (Sze), 10.44
mysqli_prepare(). problem solved.

;]
13

Programozni

janoszen · 2011. Nov. 16. (Sze), 12.02
Programozni tudni kell, ezen semmi nem segít.

A másik viszont az, hogy rengeteg olyan "fejlesztővel" találkoztam már, aki a fentihez hasonló cikkekből kiindulva váltig állította, hogy a natív MySQL library szar és közben lövése nem volt a dolgok hátteréről, ezért hevesen ellenzem a fentihez hasonló cikkek terjesztését. Tipikus szenzációhajhász, szándékos vagy tudatlanságból adódó ferdítéseket tartalmazó írás. Inkább elmondhatta volna a t. szerző, hogy mi a dolog háttere és hogy kell ellene védekezni.
14

A mysql library (feltéve,

H.Z. v2 · 2011. Nov. 16. (Sze), 12.55
A mysql library (feltéve, hogy ugyanarról beszélünk) főként azért "szar", mert nem fejlesztik tovább, helyette lenne a mysqli - ha ragaszkodunk ahhoz, hogy MySQL. PDO-t csak azért preferálnám, mert később valamivel egyszerűbb más adatbázist mögé tenni, ha úgy adódna.
16

később valamivel egyszerűbb

Hidvégi Gábor · 2011. Nov. 16. (Sze), 13.54
később valamivel egyszerűbb más adatbázist mögé tenni, ha úgy adódna
szívesen megkérdeznék száz programozót, hogy életük eddigi összes munkájában hányszor fordult elő, hogy adatbázisrendszert cserélni
17

Egyszer

Poetro · 2011. Nov. 16. (Sze), 14.41
Mi egyszer álltunk át PostgreSLQ-ről MySQL-re. És ugyan használtunk egy adatbázisréteget, a lekérdezések több mint 50%-át át kellett így is írni. Persze ez nem ma volt, hanem kb. 5 éve, azóta valószínűleg sokat fejlődtek ezek a rétegek, és tudtommal akkor még például (használható) PDO se volt.
19

Amennyire tudom (láttam/meg

H.Z. v2 · 2011. Nov. 16. (Sze), 15.05
Amennyire tudom (láttam/meg mostanság tapasztalom) az egyik legnagyobb gond ezekkel az átállásokkal, hogy az SQL minden, csak nem szabvány. Egy MySQL-re írt rendszert elég macerás áttenni mondjuk Oracle-re, ha eredendően nem úgy készültek, hogy amennyire lehet, csak a mindenütt működő megoldásokat használják.
18

Én csak rendszergazdaként

H.Z. v2 · 2011. Nov. 16. (Sze), 15.03
Én csak rendszergazdaként asszisztáltam ilyesmihez. ;-)
Ne abban gondolkodj, hogy x megrendelőnek készítesz y rendszert, hanem mondjuk a Drupal készítőinek a fejével! Ők nem készülhetnek arra, hogy kizárólag MySQL-t tehetnek a rendszerük mögé. (bocs, Drupal csak egy hirtelen jött példa volt, nem tudom, képes-e mást is használni)
20

Értem, tehát a feladata

Hidvégi Gábor · 2011. Nov. 16. (Sze), 15.30
Értem, tehát a feladata válogatja, hogy hol érdemes ilyen absztrakciós réteget bevezetni. A Poetro-féle tíz év (valahol írtad, hogy ennyi ideje vagy a szakmában)/egy átállás lehet szerintem is az átlagos szám. Köszi a válaszokat.
21

test

Greg · 2011. Nov. 16. (Sze), 15.52
Nalam a test adatbazis az esetek 90%-aban sqlite az eles az pedig mysql. Ugyhogy en a 2-t parhuzamosan hasznalom, de en speciel szeretem az adatbazistol fuggetlenre epiteni a dolgokat, hogyha barmilyen okbol valtani kell, akkor fajdalommentes legyen.
22

Ha az az integer érték type

prom3theus · 2011. Nov. 16. (Sze), 16.45
Ha az az integer érték type cast-olva van (int)-tel, akkor nem sűrűn lehet belőle biztonsági kockázat.

De lehet én értettem valamit félre, amire gondolok:

$query = 'SELECT * FROM "foo" WHERE "id" = '.(int)$fooId.' AND "bar" = 2';
mysql_query(...);
Ettől függetlenül bármilyen string-re vagy nem egyértelműen numerikus adattípusú változóra (vagy tömb/objektum elemre) valamelyiket alkalmazni KELL:
- mysql_real_escape_string() - csak mysql esetén, amúgy addslashes() még esetleg (az is jobb, mint a semmi)
- PDO::quote()

vagy PDO prepared statement esetén - tehát a PDO::prepare() hívással visszakapott objektumon hívott - PDOStatement::bind***() metódusok használata, ha az előző kettő nem felel meg a céloknak vagy a meglévő eszközökkel nem teljesen férnek össze.

Persze ha adatbázis absztrakciós réteget használunk a PDO (vagy bármi) felett, akkor annak a dokumentációja mérvadó - a kulcsszavak ebben az esetben: "SQL injection", "SQL security", "escaping SQL queries" és hasonlók :)
23

A bind-olt megoldást miért

H.Z. v2 · 2011. Nov. 16. (Sze), 17.35
A bind-olt megoldást miért tetted a lista végére? Van valami ok rá, hogy kerüljem a használatát (a valamivel több gépelést leszámítva) ?
15

csak hogy írjak valami konstruktívat is

Crystal · 2011. Nov. 16. (Sze), 13.45
hello,

ha most kezded a PHP-t akkor erősen javallanám ennek a könyvnek a beszerzését: http://www.sitepoint.com/books/phppro1/toc.php

Ezen kívül a legtöbb szakirodalom elavult, a "netes tutorialok" 95%-ának pedig a béka segge alatt van a minősége. Ha ezekből tanulsz, akkor csak nagyon sokára fogod rendesen megtanulni a szakmát.

A fenti könyvöm kívül a php.net legyen az elsődleges információforrásod, továbbá érdemes lenne elkezdened hasznléni egy keretrendszert minél hamarabb (ha már pár hónapja tanulsz akkor pont ideje). Egyrészt azért, mert elég sokat segítenek abban, hogy ne olyan "éppen működő de amúgy katasztrofális" kódot írj, másrészt mert rengeteget fejlődhetsz, ha belenézel a forráskódjukba, harmadrészt mert - ha kellő tapasztalatod van egy adott rendszer használatában - akkor jelentősen gyorsítják a fejlesztés sebességét. Később persze dönthetsz úgy, hogy nem kell neked semmilyen keretrendszer, vannak seniorok között is ilyen no-framework fejlesztők, de egyelőre - elsősorban tanulási célból - nagyon javallott valami framework használata.
2

uh. ma is rosszat fogok

Crystal · 2011. Nov. 15. (K), 15.15
uh. ma is rosszat fogok álmodni -.-
5

BOM

Greg · 2011. Nov. 15. (K), 15.32
mentsd a fajlt utf8 without BOM modban. Es ne hasznalj ilyen SQL lekerdezeseket, mert nagyon nem biztonsagos.
24

Milyen SQL-Injection?!

Pepita · 2011. Nov. 20. (V), 17.41
Sokan írták a veszélyt, én azt kérdezném, miért?
Ott van az a feltétel, hogy: if(mysql_num_rows($result)==1), ami - szerintem - egyértelműen jelzi, hogy csak 1 db eredmény esetén ok!
Megjegyzem, én ezután még ráellenőriznék, hogy a $result[name]==$name and $result[pass]==$pass és akkor már majdnem tutira mentem, mindenféle real_escape-ek nélkül, és akkor nem is kell vitatkozni annak használhatóságáról...
25

fail

H.Z. v2 · 2011. Nov. 20. (V), 18.09
1. Nagyon rossz gyakorlat, ha valaki ilyen alapon, hogy "itt úgysem lehet SQL injection" kihagyja a szükséges ellenlépéseket, amik valóban megakadályozzák az injection-t.
2. Hecc kedvéért jelszóként kapott injection végére még odabiggyeszt egy LIMIT 1-t és akkor a sorszámlálód már semmit sem ér.

Ha meg az adatbázisban plain textben tárolod a jelszavakat... na erre inkább nem mondanék semmit.
27

re: fail

Pepita · 2011. Nov. 20. (V), 20.13
1. Nem állítottam:
itt úgysem lehet SQL injection

2. Köszönöm a kiigazítást ezt most tényleg benéztem, mentem az oldalt figyelmeztetőnek!

Ha meg az adatbázisban plain textben tárolod a jelszavakat... na erre inkább nem mondanék semmit.

Nem én, egyébként van rajta - ha jól láttam - md5, én azt a változót használtam... Persze lehetne több, mint md5.

Későbbi szerk.:
Megjegyzem, én ezután még ráellenőriznék, hogy a $result[name]==$name and $result[pass]==$pass

,tehát 2.-ben "nem annyira" köszönöm a kiigazítást, kiragadtad egy mondatomat, nem tekintve, hogy mit írtam utána. Sztem így is lehet, nem csak realslash-el. Ha nem ok, akkor bocs a tévedésért.
26

Sokan írták a veszélyt, én

kuka · 2011. Nov. 20. (V), 18.17
Sokan írták a veszélyt, én azt kérdezném, miért?
Felebarátaik iránti szeretetből.

mapdesign18 a veszély szemléltetésével kezdi a hozzászólását. Olvasd el.