Easy Coding
  Forum Wiki Tagging Projekte Karte RSS
» Start
» All Recent Changes
» Wiki Suche
» Wiki Hilfe

Coder How To's

Algorithmen Informationen

edit SideBar

Neue Wiki Eintrage finden Sie unter easy-coding.de/wiki.

Sicherer AJAX Login mit Seed

Der Ordner seed ist zu erstellen und mit Schreibrechten zu versehen. Ferner ist eine Benutzerdatenbank anzulegen. Einen Download findet ihr im Forum.

Vom Forum könnt ihr auch die benötigte md5.js beziehen.

Hinweise wie ihr euer Login noch sicherer machen könnt:

  • um gegen Bruteforce gewappnet zu sein, sperrt die IP Adresse des Clients nach 3 erfolglosen Login-Versuchen
  • löscht die Seed Dateien nach erfolgreicher Authentifizierung oder nach x Minuten

Wie funktioniert das?

Der Server generiert serverseitig ein einmaliges Token mit zufälligen Zeichen (im englischen wird hier oft von einem “Seed” gesprochen). Dieses Token wird anschließend im Browser verwendet um das schon gehashte Passwort noch einmal ein eine neues Hash umzuwandeln. Die Daten werden anschließend an den Server übertragen. Das in der Datenbank gespeicherte Passwort-Hash wird nun auch mit dem Token in ein neues Hash umgewandelt und mit dem vom Browser übertragenen Wert verglichen. Stimmen die beiden Hashwerte überein sind auch die eingegebenen Daten korrekt und der User hat sich authentifiziert.

Wichtig bei dieser Vorgehensweise ist, dass das Token immer nur ein einmaliges Token ist. Bei jeder Anfrage wird das Token neu generiert und ist nur für einen Versuch gültig. So kann ein abgehörtes Hash, was im Browser generiert wurde, nicht noch einmal verwendet werden.

login.html
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2.         "http://www.w3.org/TR/html4/loose.dtd">
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  4. <title>Coder Wiki - Secure AJAX Login</title>
  5. <script src="md5.js" type="text/javascript">
  6. // javascript md5 encoder originated from <http://pajhome.org.uk/crypt/md5/>
  7. // used under license as outlined at <http://pajhome.org.uk/site/legal.html>
  8. // Copyright (c) 1998 - 2002, Paul Johnston & Contributors
  9. // All rights reserved.
  10. </script>
  11. <script type="text/javascript">
  12. <!--
  13. //author: d0nut at coder-wiki.de
  14. var seed_hash, seed_id;
  15.  
  16. function ajax(send) {
  17.         var req;
  18.  
  19.         try {
  20.                 req = window.XMLHttpRequest ? new XMLHttpRequest() :
  21.                                 new ActiveXObject("Microsoft.XMLHTTP");
  22.         } catch (e) {
  23.                 //Kein AJAX Support
  24.         }
  25.         req.onreadystatechange = function() {
  26.                 if ((req.readyState == 4) && (req.status == 200)) {
  27.                         if(send == 'gethash=true') {
  28.                                 var tmp = req.responseText.split('|');
  29.                                 seed_id = tmp[0];
  30.                                 seed_hash = tmp[1];
  31.                         } else {
  32.                                 var msg = 'login = '+(req.responseText=='true' ? 'ok' : 'false');
  33.                                 document.getElementById('message').innerHTML = msg;
  34.                         }
  35.                 }
  36.         }
  37.  
  38.         req.open('POST', 'secure.php');
  39.         req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  40.         req.send(send);
  41. }
  42.  
  43. function getSeed() {
  44.         ajax('gethash=true');
  45. }
  46.  
  47. function loginSeed(username, password) {
  48.         if(seed_hash == null || seed_id == null) return;
  49.  
  50.         var hash = hex_md5(hex_md5(password) + seed_hash);
  51.         ajax('username='+username+'&hash='+hash+'&id='+seed_id);
  52.  
  53.         return false;
  54. }
  55. //-->
  56. </script>
  57. </head>
  58.  
  59. <body onload="getSeed()">
  60.  
  61. <h1>Secure AJAX Login</h1>
  62.  
  63. <div id="message">&nbsp;</div>
  64.  
  65. <form action="post" onsubmit="return loginSeed(this.username.value, this.password.value);">
  66.         Benutzername: <input type="text" name="username" size="20" /><br />
  67.         Passwort: <input type="password" name="password" size="20" /><br />
  68.         <input type="submit" />
  69. </form>
  70.  
  71. </body>
  72. </html>
secure.php
  1. <?php
  2. //author: d0nut at coder-wiki.de
  3. //Erstellt eine zufällige Zeichenkombination aus Zahlen, Klein- & Großbuchstaben
  4. function generate_seed($length) {
  5.         $seed = "";
  6.         for($i=0; $i<$length; $i++) {
  7.                 $array[1] = chr(rand(48,57));
  8.                 $array[2] = chr(rand(65,90));
  9.                 $array[3] = chr(rand(97,122));
  10.                 $seed .= $array[rand(1,3)];
  11.         }
  12.         return $seed;
  13. }
  14.  
  15. $folder = 'seed';
  16. $user = $_POST['username'];
  17. $pw = $_POST['password'];
  18.  
  19. //Die Benutzerdatenbank wird im Ordner seed in der Datei user.txt platziert
  20. //Benutzernamen durch Zeilen getrennt, das Passwort jeweils mit einem Tabulator eingerückt
  21. $userdb = $folder.'/userdb.txt';
  22.  
  23. if($_POST['gethash']) {
  24.         $id = time();
  25.         $seed_filename = $folder.'/'.$id;
  26.         $hash = generate_seed(16);
  27.         $handle = fopen($seed_filename, 'w');
  28.         fwrite($handle, $hash);
  29.         fclose($handle);
  30.         die($id.'|'.$hash);
  31.  
  32. } else if($_POST['username'] && $_POST['hash']) {
  33.  
  34.         $seed_filename = $folder.'/'.$_POST['id'];
  35.         if(!is_file($seed_filename))
  36.                 die('no hash'); //Es existiert keine Hash Datei mit der übermittelten ID
  37.  
  38.         //Durchsuche die Benutzerdatenbank und schaue nach dem md5 Passwort
  39.         $file = file($userdb);
  40.         foreach($file as $row) {
  41.                 $row = explode("\t", $row);
  42.                 if($user == $row[0]) {
  43.                         $pw_result = trim($row[1]);
  44.                         break;
  45.                 }
  46.         }
  47.  
  48.         if(!isset($pw_result))
  49.                 die('no user');
  50.  
  51.         $seed = file_get_contents($seed_filename);
  52.         if(md5($pw_result.$seed) == $_POST['hash'])
  53.                 die('true');
  54. }
  55. ?>

Links

Zuletzt geändert am 17.01.2008 20:47 Uhr
  Impressum