Avatar billede angelenglen Nybegynder
22. januar 2003 - 15:51 Der er 14 kommentarer og
2 løsninger

WWW-Authenticate med users fra database

lige nu bruger jeg følgende script til login-script til min admin-side, men jeg har brug for at det henter de(t) korrekt usernames/passwords fra en mysql database.
hvordan kan den laves om til det, istedet for som mu kun at have ét korrekt username og password.
---connectdb.php starts here:---
<?
if ((!isset( $PHP_AUTH_USER )) || (!isset($PHP_AUTH_PW))) {
header( 'WWW-Authenticate: Basic realm="site administration"' );
header( 'HTTP/1.0 401 Unauthorized' );
echo 'Authorization Required.';
exit;
} else {

if ($PHP_AUTH_USER == "administrator" AND $PHP_AUTH_PW == "killthemall") {
?>
<?
mysql_connect("localhost","adminusername","adminpassword");
mysql_select_db("site_dk_db");
}
else {
header( 'WWW-Authenticate: Basic realm="site administration"' );
header( 'HTTP/1.0 401 Unauthorized' );
echo 'Authorization Required.';
exit;
}
}

?>

---connectdb.php stops here:---
Avatar billede miraculix Nybegynder
22. januar 2003 - 16:10 #1
For at klarificere: Ønsker du at chekke mod mysql databasebrugere, eller snakker vi om at brugerne og deres passwords er gemt i en tabel i databasen?
Avatar billede angelenglen Nybegynder
22. januar 2003 - 16:19 #2
brugere og deres passwords er gemt i en tabel i databasen.
Avatar billede miraculix Nybegynder
22. januar 2003 - 17:23 #3
1) Først sikrer du dig at den der logger ind ikke har lavet numre med brugernavnet:
$user = addslashes($PHP_AUTH_USER);
(Det er for at undgå at brugeren kan ødelægge din sql sætning der følger om lidt)

2) Så laver du først en søgning i databasen på brugernavnet
{ connect kode som du skriver den, men med $link = mysql_connect... }
$qry = mysql_query('select username, password from usertabel where username = '.$user.', $link);

3) Så chekker du at du kun fandt een række vha. mysql_num_rows($qry);

4) Så henter du rækken vha. mysql_fetch_row();

5) Så sammenligner du det password du har fundet med det brugeren har indtastet.

Hvis noget ikke chekker ud ok undervejs afviser du brugeren.

Den besværlige fremgangsmåde er for at sikre at brugeren ikke kan fuske med passwordet. Hvis du nu havde slået op i databasen med "where username = '".$PHP_AUTH_USER."' and password = '".$PHP_AUTH_PASSWD."'"  og brugeren har indtastet passwordet "' OR 1=1" så ville databasen returnere at den fandt noget og brugeren ville kunne logge på uden et korrekt password.

(Man kan chokeres over hvor mange sites der indeholder denne usikkerhed)

Hvis der er nogen af trinene du vil have uddybet, så bare sig til..
Avatar billede angelenglen Nybegynder
22. januar 2003 - 17:31 #4
hmm kan du eventuelt lave et brugbart eksempel?
Avatar billede swaxi Nybegynder
22. januar 2003 - 18:30 #5
følgende kode omgår det samme problem på en lidt anden måde. til gengæld er det ikke så smart, hvis der er mange brugere i databasen (altså hvis du f.eks har flere hundrede)
<?
if ((!isset( $PHP_AUTH_USER )) || (!isset($PHP_AUTH_PW))) {
    header( 'WWW-Authenticate: Basic realm="site administration"' );
    header( 'HTTP/1.0 401 Unauthorized' );
    echo 'Authorization Required.';
    exit;
} else {


    mysql_connect("localhost","adminusername","adminpassword");
    mysql_select_db("site_dk_db");
    // forudsætter en tabel "brugere" med to felter "brugernavn" og "password"
    $query = 'SELECT `brugernavn`,`password` FROM `brugere`';
    $result = mysql_query($query) or die(mysql_error());
    while ($row = mysql_fetch_array($result)) {
    if ($PHP_AUTH_USER==$row['brugernavn'] && $PHP_AUTH_PW==$row['password']) {
    ?>
    <?
    } else {
        header( 'WWW-Authenticate: Basic realm="site administration"' );
        header( 'HTTP/1.0 401 Unauthorized' );
        echo 'Authorization Required.';
        exit;
    }
}
?>
Avatar billede miraculix Nybegynder
22. januar 2003 - 18:38 #6
Udmærket eksempel og metode
Avatar billede angelenglen Nybegynder
22. januar 2003 - 18:56 #7
det ser meget interessant ud, men nogen speciel grund til at det ikke er så smart med flere hundrede brugere? (for realistisk set kunne min side meget vel gå hen of få flere hundrede brugere - måske endda tusinde.)
Avatar billede miraculix Nybegynder
22. januar 2003 - 19:57 #8
Ja. Problemet er at metoden henter ALLE brugere i databasen og chekker hver eneste af dem.

Det der er smart ved en database er netop at den hurtigt kan finde en bestemt post i databasen (altså en bestemt bruger). En metode der bruger en database vil kun blive lidt langsommere når antallet af brugere fordobles.

Den viste metode vil (ca. og i snit) blive ca. dobbelt så langsom med dobbelt antal brugere.

Men det er først et problem når man kommer rigtig højt op, for man kan løbe mange brugere igennem i sekundet.

Men hov, der er vist en lille bug: Den vil afvise alle brugere undtagen den første i databasen, fordi den afviser den første gang en funden bruger ikke matcher.

Giv mig lige et øjeblik så skal jeg sende et eksempel på den metode jeg beskrev længere oppe.
Avatar billede swaxi Nybegynder
22. januar 2003 - 20:19 #9
>Den viste metode vil (ca. og i snit) blive ca. dobbelt så langsom med dobbelt antal brugere.

deeeet er jo nok en grov overdrivelse, men jeg ville ikke bruge det med flere end 100 brugere. alternativt kunne man nøjes med at teste imod database første gang, og herefter gemme data i session. så gør det ikke så meget at det tager lidt tid. men du har da ret miraculix, det ville være mere korrekt at nøjes med at udtage den post man har brug for, det var bare lige noget kode jeg alligevel havde liggende ...

> Men hov, der er vist en lille bug ...
nåja ... der skulle nok have stået noget a la

    (...)
    $flag = false;
    while ($row = mysql_fetch_array($result))
        if ($PHP_AUTH_USER==$row['brugernavn'] && $PHP_AUTH_PW==$row['password'])
            $flag = true;
    if ($flag) {
?>
<?
    } else {
        header( 'WWW-Authenticate: Basic realm="site administration"' );
        header( 'HTTP/1.0 401 Unauthorized' );
        echo 'Authorization Required.';
        exit;
    }
}
?>
Avatar billede miraculix Nybegynder
22. januar 2003 - 20:44 #10
Her er mit bud (tak til swaxi for dele af koden ;-) ):
<?

function afvis() {
    header( 'WWW-Authenticate: Basic realm="site administration"' );
    header( 'HTTP/1.0 401 Unauthorized' );
    echo 'Authorization Required.';
}

if ((!isset( $PHP_AUTH_USER )) || (!isset($PHP_AUTH_PW))) {
    afvis();
    exit;
}
// følgende har kun effekt hvis brugeren har indtastet plinger (') el. lign i brugernavn:
$user = addslashes($PHP_AUTH_USER);

mysql_connect("localhost","adminusername","adminpassword");
mysql_select_db("site_dk_db");

// forudsætter en tabel "brugere" med to felter "brugernavn" og "password"
// samt at brugernavne er unikke...

$query = "SELECT `brugernavn`,`password` FROM `brugere` where `brugernavn` = '".$user."'";

$result = mysql_query($query) or die(mysql_error());

if ( mysql_num_rows($result) != 1 ) {
  afvis();
  exit();
}

if ($row = mysql_fetch_array($result) ) {
    if ($PHP_AUTH_USER==$row['brugernavn'] && $PHP_AUTH_PW==$row['password']) {
    ?>
      VELKOMMEN TIL MIN SIKRE SIDE
    <?
    } else {
        afvis();
        exit;
    }
} else {
    afvis();
    exit;
}
?>

swaxi: Kan du ikke lige forklare mig hvorfor det er en _grov_ overdrivelse? Det gælder naturligvis kun ved højt antal brugere (altså hvor gennemløbet af løkken bliver den dominerende faktor) Jeg har aldrig været en ørn til kompleksitetsberegning, men jeg synes da logisk at det må være rigtigt alligevel? No hard feelings, jeg er bare nysgerrig ;-)
Avatar billede swaxi Nybegynder
22. januar 2003 - 23:59 #11
jeg mente ikke noget særligt med ordet grov .. bare at det var lidt ... hm ... det er en stor overdrivelse. altså ... jeg mente ikke at _du_ var grov ... :)

det der tager længere tid ved denne metode er primært at flytte data mellem mysql og php, og siden det er to processer, der kører samtidig og vi måske taler om nogle få kilobytes, tager det nok ikke mange clockcycles. til gengæld tager det nok væsentligt længere tid at forbinde til databasen, starte processerne op etc. så derfor bliver slutresultatet nok ikke så forskelligt igen.
Avatar billede miraculix Nybegynder
23. januar 2003 - 00:57 #12
Der har du helt ret. Det var også derfor jeg skrev det med:

"Men det er først et problem når man kommer rigtig højt op, for man kan løbe mange brugere igennem i sekundet."

Men når du så kommer der op af så er den også lineær.

Jeg forstod godt det med at _grov_ gik på overdrivelsen og ikke på mig. No offence taken, jeg troede bare jeg havde regnet helt fuldstændigt galt.. ;-)

I øvrigt er databaseudgaven også lineær, hvis brugernavns-feltet ikke er indexeret. Men det kan løses med et snuptag.
Avatar billede swaxi Nybegynder
23. januar 2003 - 01:24 #13
mkay ... moderne processorer kan levere noget i retning af et par miliarder instruktioner pr. sekundt. derfor er det meget sjældent at flaskehalsen i et phpscript ligger i beregningsdelene. istedet kan det betale sig at minimere antallet (og omfanget) af IO-bursts. dvs. filsystemet primært.
jeg vil tro at mysql skal læse de samme mængder data ind fra filsystem hvad enten den skal lave en select og returnere een række eller om den skal blot returnere alle rækker (fra den samme tabel forstås).
det der tager længere tid bliver så overførelsen af data mellem mysql og php. det tror jeg som nævnt hellerikke der er det store påstyr ved, da vi - selv med flere tusinde brugere - taler relativt få data, der jo bare skal kopieres rundt i maskinens ramkredse.
herefter bruger php-scriptet self. lidt tid på løkken, men det er jvf ovenstående en dråbe i havet. (desuden svarer det omtrent til den tid mysql eksekverer hurtigere, pga. et simplere query)

derfor tror jeg at eksekveringstiden forbliver ganske lav, selv ved mange brugere, men derudover syntes jeg da personligt at det ser smukkere ud, hvis man kan lægge så meget arbejde over i databasen som muligt.
Avatar billede miraculix Nybegynder
23. januar 2003 - 01:34 #14
Right on
Avatar billede swaxi Nybegynder
23. januar 2003 - 02:07 #15
for lige at konkludere lidt, så tror jeg altså at, hvis man virkelig vil speede det lidt op, så skal man lade være med at checke brugeren hver gang siden loades (som det sker nu). istedet kan man nøjes med at checke første gang, og så gemme oplysningerne om bruger+pass i en sessionvariabel.

på den måde slipper man helt for at skulle igang med at slå op i database mere end een gang (og for den ene gangs skyld er det vel underordnet om det tager 1/10 eller 1/2 sekundt at eksekvere ...)
Avatar billede angelenglen Nybegynder
15. februar 2003 - 12:10 #16
Jeg har delt points'ne lidt ud  det virker som om miraculix var inspireret af swaxi, så derfor har swaxi fået de fleste points.

Tak for svaret, håber i er tilfreds med points'ne.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester